更新 zip 时出现内存不足异常
Out of memory exception while updating zip
我在尝试将文件添加到 .zip 文件时收到 OutofMemoryException
。我正在使用 32 位架构来构建和 运行 应用程序。
string[] filePaths = Directory.GetFiles(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\capture\capture");
System.IO.Compression.ZipArchive zip = ZipFile.Open(filePaths1[c], ZipArchiveMode.Update);
foreach (String filePath in filePaths)
{
string nm = Path.GetFileName(filePath);
zip.CreateEntryFromFile(filePath, "capture/" + nm, CompressionLevel.Optimal);
}
zip.Dispose();
zip = null;
我无法理解背后的原因。
确切原因取决于多种因素,但很可能您只是向存档中添加了太多内容。尝试使用 ZipArchiveMode.Create
选项,它将存档直接写入磁盘而不将其缓存在内存中。
如果您真的想更新现有存档,您仍然可以使用 ZipArchiveMode.Create
。但它需要打开现有存档,将其所有内容复制到新存档(使用 Create
),然后添加新内容。
如果没有 good, minimal, complete code example,就无法确定异常的来源,更不用说如何修复了。
编辑:
我的意思是“...打开现有存档,将其所有内容复制到新存档(使用 Create
),然后添加新内容”:
string[] filePaths = Directory.GetFiles(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\capture\capture");
using (ZipArchive zipFrom = ZipFile.Open(filePaths1[c], ZipArchiveMode.Read))
using (ZipArchive zipTo = ZipFile.Open(filePaths1[c] + ".tmp", ZipArchiveMode.Create))
{
foreach (ZipArchiveEntry entryFrom in zipFrom.Entries)
{
ZipArchiveEntry entryTo = zipTo.CreateEntry(entryFrom.FullName);
using (Stream streamFrom = entryFrom.Open())
using (Stream streamTo = entryTo.Open())
{
streamFrom.CopyTo(streamTo);
}
}
foreach (String filePath in filePaths)
{
string nm = Path.GetFileName(filePath);
zipTo.CreateEntryFromFile(filePath, "capture/" + nm, CompressionLevel.Optimal);
}
}
File.Delete(filePaths1[c]);
File.Move(filePaths1[c] + ".tmp", filePaths1[c]);
或类似的东西。由于缺少好的 minimal、complete 代码示例,我只是在浏览器中编写了上面的代码。我没有尝试编译它,更不用说测试它了。您可能想要调整一些细节(例如临时文件的处理)。但希望你明白了。
原因很简单。 OutOfMemoryException 表示内存不足以执行。
压缩占用大量内存。不能保证改变逻辑就能解决问题。但是你可以考虑不同的方法来缓解它。
1。
由于您的主程序必须是 32 位的,您可以考虑启动另一个 64 位进程来进行压缩(使用 System.Diagnostics.Process.Start
)。在 64 位进程完成其工作并退出后,您的 32 位主程序可以继续。您可以简单地使用系统上已经安装的工具,或者自己编写一个简单的程序。
2。
另一种方法是在每次添加条目时进行处置。
ZipArchive.Dispose
保存文件。每次迭代后,可以释放分配给 ZipArchive
的内存。
foreach (String filePath in filePaths)
{
System.IO.Compression.ZipArchive zip = ZipFile.Open(filePaths1[c], ZipArchiveMode.Update);
string nm = Path.GetFileName(filePath);
zip.CreateEntryFromFile(filePath, "capture/" + nm, CompressionLevel.Optimal);
zip.Dispose();
}
这种方法并不简单,可能不如第一种方法有效。
我在尝试将文件添加到 .zip 文件时收到 OutofMemoryException
。我正在使用 32 位架构来构建和 运行 应用程序。
string[] filePaths = Directory.GetFiles(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\capture\capture");
System.IO.Compression.ZipArchive zip = ZipFile.Open(filePaths1[c], ZipArchiveMode.Update);
foreach (String filePath in filePaths)
{
string nm = Path.GetFileName(filePath);
zip.CreateEntryFromFile(filePath, "capture/" + nm, CompressionLevel.Optimal);
}
zip.Dispose();
zip = null;
我无法理解背后的原因。
确切原因取决于多种因素,但很可能您只是向存档中添加了太多内容。尝试使用 ZipArchiveMode.Create
选项,它将存档直接写入磁盘而不将其缓存在内存中。
如果您真的想更新现有存档,您仍然可以使用 ZipArchiveMode.Create
。但它需要打开现有存档,将其所有内容复制到新存档(使用 Create
),然后添加新内容。
如果没有 good, minimal, complete code example,就无法确定异常的来源,更不用说如何修复了。
编辑:
我的意思是“...打开现有存档,将其所有内容复制到新存档(使用 Create
),然后添加新内容”:
string[] filePaths = Directory.GetFiles(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\capture\capture");
using (ZipArchive zipFrom = ZipFile.Open(filePaths1[c], ZipArchiveMode.Read))
using (ZipArchive zipTo = ZipFile.Open(filePaths1[c] + ".tmp", ZipArchiveMode.Create))
{
foreach (ZipArchiveEntry entryFrom in zipFrom.Entries)
{
ZipArchiveEntry entryTo = zipTo.CreateEntry(entryFrom.FullName);
using (Stream streamFrom = entryFrom.Open())
using (Stream streamTo = entryTo.Open())
{
streamFrom.CopyTo(streamTo);
}
}
foreach (String filePath in filePaths)
{
string nm = Path.GetFileName(filePath);
zipTo.CreateEntryFromFile(filePath, "capture/" + nm, CompressionLevel.Optimal);
}
}
File.Delete(filePaths1[c]);
File.Move(filePaths1[c] + ".tmp", filePaths1[c]);
或类似的东西。由于缺少好的 minimal、complete 代码示例,我只是在浏览器中编写了上面的代码。我没有尝试编译它,更不用说测试它了。您可能想要调整一些细节(例如临时文件的处理)。但希望你明白了。
原因很简单。 OutOfMemoryException 表示内存不足以执行。
压缩占用大量内存。不能保证改变逻辑就能解决问题。但是你可以考虑不同的方法来缓解它。
1。
由于您的主程序必须是 32 位的,您可以考虑启动另一个 64 位进程来进行压缩(使用 System.Diagnostics.Process.Start
)。在 64 位进程完成其工作并退出后,您的 32 位主程序可以继续。您可以简单地使用系统上已经安装的工具,或者自己编写一个简单的程序。
2。
另一种方法是在每次添加条目时进行处置。
ZipArchive.Dispose
保存文件。每次迭代后,可以释放分配给 ZipArchive
的内存。
foreach (String filePath in filePaths)
{
System.IO.Compression.ZipArchive zip = ZipFile.Open(filePaths1[c], ZipArchiveMode.Update);
string nm = Path.GetFileName(filePath);
zip.CreateEntryFromFile(filePath, "capture/" + nm, CompressionLevel.Optimal);
zip.Dispose();
}
这种方法并不简单,可能不如第一种方法有效。