首页 > 技术文章 > 记一次使用SevenZip发生的Bug

ACDIV 2020-07-15 10:34 原文

最近写程序有一个需求,就是解压ZIP,然后把文件压缩成7Z,由于不希望产生IO操作,以及解压成文件打包完以后又删除文件这一套操作太过于繁琐,所以打算全程都用流进行。

解压操作相对简单

var FILE = new Dictionary<string, Stream>();
using (ZipArchive archive = new ZipArchive(File.OpenRead(@"Y:\SystemBackup\JD02 11# 中脚.zip"), ZipArchiveMode.Read))
{
       foreach (var item in archive.Entries)
    {
      var Mem = new MemoryStream();
      item.Open().CopyTo(Mem);
      FILE.Add(item.FullName, Mem);
    }
 }

使用上述代码就能将压缩包内的文件解压成内存流,保存到Dictionary里面。

然后调用SevenZip库压缩成7Z也相对简单

using (var SaveF = new FileStream("1.7z", FileMode.Create, FileAccess.Write))
{
    var compressor = new SevenZipCompressor
    {
        ArchiveFormat = OutArchiveFormat.SevenZip,
        CompressionLevel = SevenZip.CompressionLevel.Ultra,
    };
compressor.CompressStreamDictionary(FILE, SaveF);
}

这样存在Dictionary流就能全部压缩到1.7z里面,然后一顿操作猛如虎,结果一看二八五。

 

 

 压缩进去的文件大小全都是0,

然后经过不懈的Debug后,终于意识到一个问题,

 

 

 内存的流的指向位置指向的是末尾,这样如果SevenZip库读取流的方式是使用ReadByte()的话,那势必是从读取的是最后一个字节,难怪大小是0;

            using (ZipArchive archive = new ZipArchive(File.OpenRead(@"Y:\SystemBackup\JD02 11# 中脚.zip"), ZipArchiveMode.Read))
            {
                using (var SaveF = new FileStream("1.7z", FileMode.Create, FileAccess.Write))
                {
                    var FILE = new Dictionary<string, Stream>();
                    var compressor = new SevenZipCompressor
                    {
                        ArchiveFormat = OutArchiveFormat.SevenZip,
                        CompressionLevel = SevenZip.CompressionLevel.Ultra,
                    };
                    foreach (var item in archive.Entries)
                    {
                        var Mem = new MemoryStream();
                        item.Open().CopyTo(Mem);
                        Mem.Position = 0;
                        FILE.Add(item.FullName, Mem);
                    }
                    compressor.CompressStreamDictionary(FILE, SaveF);

                }
            }

在此警示自己,不管如果,在操作流之前,最好先手动把流的指向指到开头位置。

那么解决方法就很简单了

 

 

 解压完以后,把内存流指向流的开头就行。

以下是代码

 

推荐阅读