記一次使用SevenZip發生的Bug
阿新 • • 發佈:2020-07-15
最近寫程式有一個需求,就是解壓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); } }
在此警示自己,不管如果,在操作流之前,最好先手動把流的指向指到開頭位置。
那麼解決方法就很簡單了
解壓完以後,把記憶體流指向流的開頭就行。
以下是程式碼