使用 Ionic 创建大型多部分 zip 失败并出现 OutOfMemoryException

Creating large multi-part zip with Ionic fails with OutOfMemoryException

我尝试使用 IonicZip 创建一个总大小为 17 GB 的多部分 zip 文件。

每个 zip 部分设置为不大于 500 MB 左右。

zip.MaxOutputSegmentSize = 500000000;

进入 zip 的文件大小各不相同,但绝不会超过 350MB,通常要小得多,只有几 KB 或 MB。

我创建 zip 文件的机器有 4GB 内存。

当我在我的程序中开始创建 zip 时,由于使用了 RAM,我在某个时候得到了一个 OutOfMemoryException

(当所有文件的总大小约为 2 GB 而不是 17GB 时,同样可以正常工作)。

代码:

ZipFile zip = new ZipFile(zipFileName, Encoding.UTF8);
zip.CompressionLevel = CompressionLevel.BestCompression;

zip.ParallelDeflateThreshold = -1; // 
zip.MaxOutputSegmentSize = 500000000; // around 500MB

[...]

while (...)
{
  zip.AddEntry(adjustedFilePath, File.ReadAllBytes(filepath));
}

zip.Save();

我想知道 IonicZip 如何结合多部分创建来处理 zip.save。应该不需要将所有的多部分都保存在内存中,而只保存当前的部分,不是吗?

并且由于我将 zip.MaxOutputSegmentSize 设置为仅约 500MB,并且进入 zip 的单个文件的最大大小永远不会超过 350MB,所以我不明白为什么它会占用这么多内存.

另一方面,当发生OutOfMemoryException 时,甚至还没有将多部分中的任何一个部分写入磁盘。通常,在成功创建 zip 的文件数量较少的情况下,多个部分位于文件系统上,具有不同的创建时间戳,大约。每人间隔5秒。所以我真的不确定 IonicZip 在内部到底在做什么,直到它吐出第一个 zip 部分。

抱歉,我是 C# 和 .NET 的新手。 IonicZip 是最好的库吗?我可以改用 System.IO.Compression 或 System.IO.Packaging 包(我没有看到它们支持多部分压缩)或商业 Xceed 吗?

我已经检查但没有帮助的帖子:

我建议使用内置的 .net System.IO.Compression 命名空间 类 到 zip/unzip 文件;它们是基于流的,而您在此处的示例不使用流 - 因此必须使用 RAM 来存储压缩数据。使用 .net 本机库,您可以将压缩数据分块写入输出流。

我提出的解决方案在工作量方面似乎是最好的(我不想重新发明轮子并为标准 zip/compression 包编写多部分逻辑,似乎这种标准的东西应该是任何压缩包的一部分)是使用 Xceed 并且几乎使用与我为 IonicZip 所做的相同的代码逻辑。

看来 IonicZip 在内存方面并没有真正有效地处理它。 Xceed 运行良好,没有显着增加内存使用量。

        using Xceed.Zip;
        using Xceed.FileSystem;

        [...]

        ZipArchive zip = new ZipArchive(new DiskFile(zipFileName));
        zip.SplitNameFormat = SplitNameFormat.PkZip;
        zip.SplitSize = 500000;
        zip.DefaultCompressionLevel = Xceed.Compression.CompressionLevel.Highest;
        zip.TempFolder = new DiskFolder(@"C:\temp");
        new DiskFolder(localSourceFolder).CopyFilesTo(zip, true, true);