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

C# 使用 SharpZipLib 實作檔案/目錄壓縮與解壓縮完整指南

     編輯:關於C#

套件簡介

ICSharpCode.SharpZipLib (簡稱 SharpZipLib) 是 .NET 經典開源壓縮庫,支援 Zip、GZip、BZip2、Tar 等格式,純 C# 實作、無外部相依、相容 .NET Framework / .NET Core / .NET 5+。NuGet 安裝:Install-Package SharpZipLib。

核心類別速查

  • ZipOutputStream:建立 Zip 檔案串流 (寫入)
  • ZipInputStream:讀取 Zip 檔案串流 (解壓)
  • ZipEntry:代表壓縮包內單一檔案/目錄項目
  • FastZip:高階封裝,一行完成目錄壓縮/解壓

場景一:壓縮指定檔案清單為 Zip

using ICSharpCode.SharpZipLib.Zip;
using System.IO;

public void CompressFiles(List files, string zipPath, int compressionLevel = 9)
{
    using (var zipStream = new ZipOutputStream(File.Create(zipPath)))
    {
        zipStream.SetLevel(compressionLevel); // 0=存儲, 9=最大壓縮

        foreach (var file in files)
        {
            using (var fs = file.OpenRead())
            {
                var entry = new ZipEntry(file.Name) { DateTime = file.LastWriteTime };
                zipStream.PutNextEntry(entry);

                byte[] buffer = new byte[4096];
                int bytesRead;
                while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) > 0)
                    zipStream.Write(buffer, 0, bytesRead);
            }
        }
        zipStream.Finish(); // 必須呼叫 Finish() 寫入中央目錄
    }
}

場景二:遞迴壓縮整個目錄 (保留相對路徑)

public void CompressDirectory(string sourceDir, string zipPath, int level = 9, bool deleteSource = false)
{
    if (!Directory.Exists(sourceDir)) throw new DirectoryNotFoundException(sourceDir);

    var files = GetAllFiles(sourceDir); // 遞迴取得所有檔案絕對路徑

    using (var zipStream = new ZipOutputStream(File.Create(zipPath)))
    {
        zipStream.SetLevel(level);

        foreach (var filePath in files)
        {
            // 計算相對路徑做為 Zip 內部路徑
            string relativePath = filePath.Substring(sourceDir.Length).TrimStart('\\', '/');
            var entry = new ZipEntry(relativePath)
            {
                DateTime = File.GetLastWriteTime(filePath),
                Size = new FileInfo(filePath).Length
            };

            using (var fs = File.OpenRead(filePath))
            {
                zipStream.PutNextEntry(entry);
                byte[] buffer = new byte[4096];
                int read;
                while ((read = fs.Read(buffer, 0, buffer.Length)) > 0)
                    zipStream.Write(buffer, 0, read);
            }
        }
        zipStream.Finish();
    }

    if (deleteSource) Directory.Delete(sourceDir, true);
}

private List GetAllFiles(string dir)
{
    var list = new List();
    foreach (var file in Directory.GetFiles(dir)) list.Add(file);
    foreach (var subDir in Directory.GetDirectories(dir)) list.AddRange(GetAllFiles(subDir));
    return list;
}

場景三:解壓縮 Zip 到指定目錄

public void DecompressZip(string zipPath, string targetDir)
{
    if (!Directory.Exists(targetDir)) Directory.CreateDirectory(targetDir);

    using (var zipStream = new ZipInputStream(File.OpenRead(zipPath)))
    {
        ZipEntry entry;
        while ((entry = zipStream.GetNextEntry()) != null)
        {
            string fullPath = Path.Combine(targetDir, entry.Name);

            if (entry.IsDirectory)
            {
                Directory.CreateDirectory(fullPath);
                continue;
            }

            // 確保父目錄存在
            string dir = Path.GetDirectoryName(fullPath);
            if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir))
                Directory.CreateDirectory(dir);

            using (var fs = File.Create(fullPath))
            {
                byte[] buffer = new byte[4096];
                int read;
                while ((read = zipStream.Read(buffer, 0, buffer.Length)) > 0)
                    fs.Write(buffer, 0, read);
            }
            // 保留檔案時間
            File.SetLastWriteTime(fullPath, entry.DateTime);
        }
    }
}

場景四:一鍵式 FastZip (最簡單)

using ICSharpCode.SharpZipLib.Zip;

var fastZip = new FastZip();
// 建立密碼保護 Zip
fastZip.CreateZip(@"C:\Output\Protected.zip", @"C:\SourceDir", true, "password");
// 解壓
fastZip.ExtractZip(@"C:\Output\Protected.zip", @"C:\ExtractDir", "password");

效能調優建議

  • 緩衝區大小: 4KB~64KB 視檔案大小調整,大檔案可用 1MB 減少系統呼叫。
  • 壓縮等級: 9 最高但最慢,6 為平衡點;大量文字/程式碼建議 9,已壓縮格式 (jpg/mp4) 建議 0 (存儲)。
  • 多執行緒: SharpZipLib 本身單執行緒,大量獨立檔案可自行 Parallel.ForEach 平行壓縮多個 Zip。
  • 記憶體: 串流式讀寫避免載入整個檔案至記憶體,適合 GB 級大檔。

常見問題

問題解決
中文檔名亂碼SharpZipLib 1.3+ 預設 UTF-8,舊版需 zipStream.UseZip64 = UseZip64.Off; entry.Name = Encoding.UTF8.GetString(Encoding.GetEncoding(950).GetBytes(name)) 等 hack,建議升級新版。
解壓後檔案 0 位元組忘記呼叫 zipStream.Finish() 或 entry.Size 未設定導致中央目錄不正確。
權限拒絕檔案被佔用、目標目錄唯讀、壓縮包需管理員權限寫入。

參考資源

原文連結:https://www.bianceng.cn/Programming/csharp/201410/45594.htm

官方 GitHub:https://github.com/icsharpcode/SharpZipLib

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