繁体   English   中英

更新 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 ),然后添加新内容。

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

编辑:

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM