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

时间:2016-08-19 06:59:31

标签: c# zip compression out-of-memory zipfile

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

每个zip部件设置为不大于500 MB。

zip.MaxOutputSegmentSize = 500000000;

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

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

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

(当所有文件的总大小约为2 GB而不是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.save。没有必要将所有多部分保存在内存中但只保留当前部分,而不是?

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

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

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

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

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

我想出的解决方案似乎是努力方面的最佳解决方案(我不想重新发明轮子并为标准的压缩/压缩包编写多部分逻辑,似乎是这样的标准的东西应该是任何压缩包的一部分)是使用http://ktoso.github.io/scala-types-of-types/并且几乎使用与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);