在c#.net中更新zip时出现内存不足exception

我在尝试在c#.net中的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 ),然后添加新内容。

如果没有一个好的, 最小的完整的代码示例 ,就不可能确定exception来自哪里,更不用说如何修复它。

编辑:

这就是我所说的“…打开现有存档,将其所有内容复制到新存档(使用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]); 

或类似的东西。 缺乏一个好的, 最小的完整的代码示例,我只是在浏览器中编写了上述内容。 我没有尝试编译它,没关系测试它。 您可能想要调整一些细节(例如临时文件的处理)。 但希望你能得到这个想法。

原因很简单。 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(); } 

这种方法并不简单,可能不如第一种方法有效。