記一次使用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); } }
在此警示自己,不管如果,在操作流之前,最好先手動把流的指向指到開頭位置。
那么解決方法就很簡單了

解壓完以后,把內存流指向流的開頭就行。
以下是代碼

浙公網安備 33010602011771號