使用Ionic创建大型多部分zip失败,导致OutOfMemoryException

本文关键字:失败 导致 OutOfMemoryException zip Ionic 创建 大型 多部 使用 | 更新日期: 2023-09-27 18:03:08

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

每个zip部分设置为不超过500mb左右。

zip.MaxOutputSegmentSize = 500000000;

压缩文件的大小各不相同,但不会超过350MB,通常要小得多,只有几个KB或MB。

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

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

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

代码:

ZipFile zip = new ZipFile(zipFileName, Encoding.UTF8);
zip.CompressionLevel = CompressionLevel.BestCompression;
zip.ParallelDeflateThreshold = -1; // https://stackoverflow.com/questions/11981143/compression-fails-when-using-ionic-zip
zip.MaxOutputSegmentSize = 500000000; // around 500MB
[...]
while (...)
{
  zip.AddEntry(adjustedFilePath, File.ReadAllBytes(filepath));
}
zip.Save();

我想知道IonicZip如何处理zip。结合多部分创建保存。它不应该是必要的持有所有的多部分在内存中,但只有当前一个,不是吗?

既然我设置了zip。MaxOutputSegmentSize仅为500MB左右,压缩后单个文件的最大大小从不超过350MB,我不明白为什么它要消耗这么多内存。

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

对不起,我是c#和。net的新手。IonicZip是最好的库吗?我是否可以使用System.IO.Compression或System.IO.Packaging包(我没有看到它们支持多部分压缩)或商业Xceed?

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

  • 使用ionic zip压缩失败
  • Ionic zip抛出内存异常
  • 使用System.IO.Packaging(与IonicZip无关)创建大型ZIP文件时出现OutOfMemoryException

使用Ionic创建大型多部分zip失败,导致OutOfMemoryException

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

我提出的解决方案似乎是最好的努力方面(我不想不得不重新发明轮子和编写多部分逻辑的标准zip/压缩包,似乎这样一个标准的事情,应该是任何压缩包的一部分)是使用Xceed和几乎使用相同的代码逻辑,就像我为IonicZip所做的。

似乎IonicZip在内存方面并没有真正有效地处理它。

        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);