记一次使用SevenZip发生的Bug
最近写程序有一个需求,就是解压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); } }
在此警示自己,不管如果,在操作流之前,最好先手动把流的指向指到开头位置。
那么解决方法就很简单了
解压完以后,把内存流指向流的开头就行。
以下是代码