1. 程式人生 > 實用技巧 >記一次使用SevenZip發生的Bug

記一次使用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);

                }
            }

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

那麼解決方法就很簡單了

解壓完以後,把記憶體流指向流的開頭就行。

以下是程式碼