C#使用SharpZipLib库压缩大文件问题

C#使用SharpZipLib库压缩文件很简单,无非引入ICSharpCode.SharpZipLib.dll:
C#使用SharpZipLib库压缩大文件问题_第1张图片
程序中引入对应的命名空间:

using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.Checksums;

这样就可以进行压缩解压操作了,网上相关代码也很多,这里就不赘述了。但是今天调试时发现个内存溢出的问题:
C#使用SharpZipLib库压缩大文件问题_第2张图片
看代码不难发现,这个缓存buffer创建的时候出现溢出。那么这个缓存创建了多大呢?fs.Length!!没错,文件多大咱就创建多大,这样相当于把整个文件放入内存,这还了得,网上果然只是示例代码,真正实用还得进行一番修改。
解决思路是开辟一个固定大小的缓存区,循环读取文件进行压缩,但是这里有个问题,压缩时是先写入ZipEntry再写入文件数据的,而ZipEntry里面包含了crc信息,不把文件读完,就计算不出来crc。所以我这里采用读取两遍文件的策略,第一遍计算crc,第二遍再写入文件数据。如果谁有更好的思路可以留言讨论。
修改之后,foreach循环里的代码如下:

int readlen = 4096000;
FileStream fs = File.OpenRead(item.Key.ToString());
byte[] buffer = new byte[4096000];       // 每次4M

ZipEntry entry = new ZipEntry(item.Key.Substring(dirPath.Length));
entry.DateTime = item.Value;
entry.Size = fs.Length;

long remaindSize = fs.Length;
// 计算crc
crc.Reset();
while (remaindSize > 0)
{
    if (remaindSize < readlen)
        readlen = (int)remaindSize;

    fs.Read(buffer, 0, readlen);
    remaindSize -= readlen;

    crc.Update(buffer, 0, readlen);
}
entry.Crc = crc.Value;
zipoutputstream.PutNextEntry(entry);

// 压缩数据
readlen = 4096000;
remaindSize = fs.Length;
fs.Seek(0, SeekOrigin.Begin);
while (remaindSize > 0)
{
    if (remaindSize < readlen)
        readlen = (int)remaindSize;

    fs.Read(buffer, 0, readlen);
    remaindSize -= readlen;
    zipoutputstream.Write(buffer, 0, readlen);
}
fs.Close();

这样改之后,再压缩大文件也就没有问题了。

你可能感兴趣的:(基础知识,C#开发)