首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# ZipHelper 壓縮解壓工具類:基於 SharpZipLib 的完整實現

     編輯:關於C語言

前言

在實際項目開發中,文件壓縮與解壓是極為常見的需求——無論是為了減少網絡傳輸帶寬,還是方便用戶批量下載資源。雖然 .NET Framework 4.5+ 內建了 ZipArchive 類,但在相容性、功能豐富度與加密支持上,第三方庫 ICSharpCode.SharpZipLib 依然是眾多開發者的首選。本文將分享一個經過項目實戰驗證的 ZipHelper 封裝類,涵蓋單文件、單目錄、多文件/目錄混合壓縮、加密壓縮與解壓等核心場景,代碼開箱即用。

核心功能一覽

  • 壓縮單個文件:支持指定壓縮等級(0-9),平衡速度與體積
  • 壓縮單個目錄:遞歸打包整個資料夾,保留目錄結構
  • 多文件/目錄混合壓縮:一次操作打包多個來源,可選密碼保護
  • 解壓縮:無需密碼即可還原,自動創建目標目錄

關鍵代碼解析

1. 壓縮單個文件 ZipFile

public void ZipFile(string filePath, string zipedFileName, int compressionLevel = 9)
{
    // 參數校驗、自動補全 .zip 後綴、創建目標目錄...
    using (var streamToZip = new FileStream(filePath, FileMode.Open, FileAccess.Read))
    using (var zipFile = File.Create(zipedFileName))
    using (var zipStream = new ZipOutputStream(zipFile))
    {
        var zipEntry = new ZipEntry(Path.GetFileName(filePath));
        zipStream.PutNextEntry(zipEntry);
        zipStream.SetLevel(compressionLevel);

        var buffer = new byte[2048];
        int size = streamToZip.Read(buffer, 0, buffer.Length);
        zipStream.Write(buffer, 0, size);
        while (size < streamToZip.Length)
        {
            int sizeRead = streamToZip.Read(buffer, 0, buffer.Length);
            zipStream.Write(buffer, 0, sizeRead);
            size += sizeRead;
        }
    }
}

亮點:流式讀寫避免大文件佔用過多內存;compressionLevel 參數讓開發者可根據場景權衡壓縮率與耗時。

2. 遞歸壓縮目錄 ZipDir

public void ZipDir(string dirToZip, string zipedFileName, int compressionLevel = 9)
{
    using (var zipOutputStream = new ZipOutputStream(File.Create(zipedFileName)))
    {
        zipOutputStream.SetLevel(compressionLevel);
        var crc = new Crc32();
        var fileList = GetAllFiles(dirToZip); // 遞歸收集所有文件路徑與修改時間

        foreach (DictionaryEntry item in fileList)
        {
            using (var fs = new FileStream(item.Key.ToString(), FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            {
                var buffer = new byte[fs.Length];
                fs.Read(buffer, 0, buffer.Length);
                var entry = new ZipEntry(Path.GetFileName(item.Key.ToString()))
                {
                    DateTime = (DateTime)item.Value,
                    Size = fs.Length
                };
                crc.Reset();
                crc.Update(buffer);
                entry.Crc = crc.Value;
                zipOutputStream.PutNextEntry(entry);
                zipOutputStream.Write(buffer, 0, buffer.Length);
            }
        }
    }
}

輔助方法 GetAllFiles / GetAllDirFiles / GetAllDirsFiles 以 Hashtable 返回「文件全路徑 → 最後修改時間」映射,確保壓縮包保留原始時間戳。

3. 多源混合壓縮與加密 ZipManyFilesOrDictorys

public bool ZipManyFilesOrDictorys(IEnumerable<string> folderOrFileList, string zipedFile, string passWord)
{
    using (var s = new ZipOutputStream(File.Create(zipedFile)))
    {
        s.SetLevel(6); // 預設中等壓縮
        if (!string.IsNullOrEmpty(passWord)) s.Password = passWord;

        foreach (var fileOrDir in folderOrFileList)
        {
            if (Directory.Exists(fileOrDir))
                ZipFileDictory(fileOrDir, s, "");
            else
                ZipFileWithStream(fileOrDir, s);
        }
        s.Finish();
        return true;
    }
}

內部私有方法 ZipFileDictory(遞歸處理子目錄)與 ZipFileWithStream(單文件流式寫入)協同工作,並在 finally 塊中顯式調用 GC.Collect() 釋放大文件句柄,體現工程化細節。

4. 解壓縮 UnZip

public void UnZip(string zipFilePath, string unZipDir)
{
    if (string.IsNullOrEmpty(unZipDir))
        unZipDir = zipFilePath.Replace(Path.GetFileName(zipFilePath), Path.GetFileNameWithoutExtension(zipFilePath)) + "/";

    using (var s = new ZipInputStream(File.OpenRead(zipFilePath)))
    {
        ZipEntry theEntry;
        while ((theEntry = s.GetNextEntry()) != null)
        {
            var directoryName = Path.GetDirectoryName(theEntry.Name);
            var fileName = Path.GetFileName(theEntry.Name);

            if (!string.IsNullOrEmpty(directoryName))
                Directory.CreateDirectory(unZipDir + directoryName);

            if (!string.IsNullOrEmpty(fileName))
            {
                using (var streamWriter = File.Create(unZipDir + theEntry.Name))
                {
                    var data = new byte[2048];
                    int size;
                    while ((size = s.Read(data, 0, data.Length)) > 0)
                        streamWriter.Write(data, 0, size);
                }
            }
        }
    }
}

自動處理目錄結構還原、空目錄創建,並以 2KB 緩衝區流式寫入,適合大型壓縮包。

完整源碼結構

ZipHelper 類位於命名空間 ZTO.PicTest.UtilitIEs,依賴 ICSharpCode.SharpZipLib.Checksums 與 ICSharpCode.SharpZipLib.Zip。類中包含:

  • 公共方法:ZipFile(兩個重載)、ZipDir、ZipManyFilesOrDictorys、UnZip
  • 私有輔助:GetAllFiles、GetAllDirFiles、GetAllDirsFiles、ZipFileWithStream、ZipFileDictory
  • 異常處理:文件不存在、路徑無效、密碼錯誤等場景均拋出具體異常

使用建議與擴展方向

  1. 依賴管理:建議通過 NuGet 安裝 SharpZipLib(Install-Package SharpZipLib),避免手動引用 DLL 版本衝突。
  2. 異步化:高併發場景下可將流操作改為 async/await 模式,避免阻塞線程。
  3. 進度回調:引入 IProgress<double> 參數,實時反饋壓縮/解壓進度。
  4. 編碼兼容:跨平台(Windows/Linux)場景注意文件名編碼,必要時設置 ZipEntry.IsUnicodeText = true。

總結

本文提供的 ZipHelper 封裝了 SharpZipLib 最常用的壓縮解壓功能,代碼結構清晰、異常處理完善、支持加密與多源混合打包,可直接集成至項目中。掌握其核心流式處理與遞歸目錄遍歷邏輯,有助於在面對更複雜的文件打包需求時靈活擴展。持續積累此類通用工具類,將顯著提升開發效率——點滴積累,開心編程!

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved