当我在 ZipFile 中添加大量数量的文件时,我遇到了 OutofMemoryException 的问题。示例代码如下:
ZipFile file = new ZipFile("E:\\test1.zip");
file.UseZip64WhenSaving = Zip64Option.AsNecessary;
file.ParallelDeflateThreshold = -1;
for (Int64 i = 0; i < 1000000; i++)
{
file.CompressionLevel = Ionic.Zlib.CompressionLevel.None;
byte[] data = Encoding.ASCII.GetBytes("rama");
ZipEntry entry = file.AddEntry(@"myFolder1/test1/myhtml111.html" + i.ToString(), data);
}
file.Save();
我已经下载了 Ionic.zip 库的源代码,我看到每个Add *()函数都有AddEntry(),AddFile()等,他们将项添加到Dictionary中称为 _entry 即可。
当我们在 ZipFile 上调用保存()或 Dispose()方法时,此词典不会清除对象
我觉得这是OutOfMemoryException的根本原因。
我如何克服这个问题?有没有其他方法可以实现相同的结果而不会遇到OutOfMemoryException?我错过了什么吗? 我也愿意使用其他开源库。
答案 0 :(得分:0)
保存档案内部结构的字典应该不成问题。 假设您输入的路径是&#39;是一个大约 50 字节的字符串 - 即使是1000000个条目也应该大约 50 Mb (很多 - 但是没有接近2 Gb的限制) - 而我没有&#39检查ZipEntry的大小 - 我也怀疑它是否足够大(每个需要大约2kb)
我也认为你对这个Entry词典的期望被清除是错误的。由于这是zip文件内容的信息结构 - 您需要它来保存所有条目。
从这一点开始,我将假设发布的代码:
byte[] data = Encoding.ASCII.GetBytes("rama");
是以字节为单位的实际文件数据的占位符(因为对于1M x 4字节 - 应该低于4Mb)
这里最有可能的问题是声明的byte []数据保留在内存中,直到整个ZipFile被释放。 保持此数组直到保存数据是有意义的。 解决此问题的最简单方法是使用重新打开和关闭ZipFile来为每个要添加的文件打包。
var zipFileName = "E:\\test1.zip";
for (int i = 0; i < 1000000; ++i)
{
using (ZipFile zf = new ZipFile(zipFileName))
{
byte[] data = File.ReadAllBytes(file2Zip);
ZipEntry entry = zf.AddEntry(@"myFolder1/test1/myhtml111.html" + i.ToString(), data);
zf.Save();
}
}
如果要保存大量小文件,这种方法可能看起来很浪费,因为直接使用byte []实现缓冲机制非常简单。
虽然确实可以通过编译为64位来解决这个问题,但除非你真的只是略微超过2Gb的限制,否则这将创建一个非常耗费内存的应用程序。 强>