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

C# 使用 SharpZipLib 實現檔案壓縮與解壓縮

     編輯:關於C語言

前言:為何選擇 SharpZipLib?

SharpZipLib (ICSharpCode.SharpZipLib) 是成熟、開源、純 .NET 實作的壓縮函式庫,支援 Zip、GZip、BZip2、Tar 等格式,無相依性、部署簡單(單一 DLL),是 .NET 壓縮作業的首選。

準備工作

  1. NuGet 安裝:Install-Package SharpZipLib
  2. 引用命名空間:
    using ICSharpCode.SharpZipLib.Zip;
    using ICSharpCode.SharpZipLib.Checksums;
    using System.IO;
    

壓縮單一檔案

public static void ZipFile(string sourceFile, string destZip, int compressionLevel = 6, int bufferSize = 4096)
{
    if (!File.Exists(sourceFile))
        throw new FileNotFoundException($"找不到檔案:{sourceFile}");

    using (var fsIn = File.OpenRead(sourceFile))
    using (var fsOut = File.Create(destZip))
    using (var zipStream = new ZipOutputStream(fsOut))
    {
        zipStream.SetLevel(compressionLevel); // 0=存儲, 9=最高壓縮
        var entry = new ZipEntry(Path.GetFileName(sourceFile))
        {
            DateTime = DateTime.Now,
            Size = fsIn.Length
        };

        // 計算 CRC32 寫入 Header,相容性更好
        var crc = new Crc32();
        var buffer = new byte[fsIn.Length];
        fsIn.Read(buffer, 0, buffer.Length);
        crc.Reset();
        crc.Update(buffer);
        entry.Crc = crc.Value;

        zipStream.PutNextEntry(entry);
        zipStream.Write(buffer, 0, buffer.Length);
        zipStream.Finish(); // 必須呼叫 Finish() 寫入中央目錄
    }
}

壓縮整個目錄(遞迴)

public static void ZipDirectory(string sourceDir, string destZip, int compressionLevel = 6)
{
    using (var fsOut = File.Create(destZip))
    using (var zipStream = new ZipOutputStream(fsOut))
    {
        zipStream.SetLevel(compressionLevel);
        var files = Directory.GetFiles(sourceDir, "*.*", SearchOption.AllDirectories);

        foreach (var file in files)
        {
            var relativePath = file.Substring(sourceDir.Length + 1).Replace('\\', '/');
            var entry = new ZipEntry(relativePath)
            {
                DateTime = File.GetLastWriteTime(file),
                Size = new FileInfo(file).Length
            };
            zipStream.PutNextEntry(entry);

            using (var fsIn = File.OpenRead(file))
            {
                var buffer = new byte[4096];
                int bytesRead;
                while ((bytesRead = fsIn.Read(buffer, 0, buffer.Length)) > 0)
                    zipStream.Write(buffer, 0, bytesRead);
            }
        }
        zipStream.Finish();
    }
}

解壓縮 Zip 檔案

public static void UnZip(string zipFile, string destDir, string password = null)
{
    if (!File.Exists(zipFile))
        throw new FileNotFoundException($"找不到壓縮檔:{zipFile}");

    Directory.CreateDirectory(destDir);

    using (var fsIn = File.OpenRead(zipFile))
    using (var zipStream = new ZipInputStream(fsIn))
    {
        if (!string.IsNullOrEmpty(password))
            zipStream.Password = password;

        ZipEntry entry;
        while ((entry = zipStream.GetNextEntry()) != null)
        {
            if (entry.IsDirectory)
            {
                Directory.CreateDirectory(Path.Combine(destDir, entry.Name));
                continue;
            }

            var fullPath = Path.Combine(destDir, entry.Name);
            var directory = Path.GetDirectoryName(fullPath);
            if (!string.IsNullOrEmpty(directory))
                Directory.CreateDirectory(directory);

            using (var fsOut = File.Create(fullPath))
            {
                var buffer = new byte[4096];
                int bytesRead;
                while ((bytesRead = zipStream.Read(buffer, 0, buffer.Length)) > 0)
                    fsOut.Write(buffer, 0, bytesRead);
            }
            // 可選:還原檔案時間
            File.SetLastWriteTime(fullPath, entry.DateTime);
        }
    }
}

WinForms 快速整合範例

private void btnCompress_Click(object sender, EventArgs e)
{
    var files = new[] { @"C:\Data\report.pdf", @"C:\Data\image.png" };
    ZipFiles(files, @"C:\Output\archive.zip");
}

private void btnExtract_Click(object sender, EventArgs e)
{
    UnZip(@"C:\Output\archive.zip", @"C:\Output\Extracted");
}

常見坑與提示

  • Finish() vs Close():ZipOutputStream 必須先呼叫 Finish() 寫入中央目錄,再 Close()(或用 using 自動處理)。
  • CRC32 與 Size:寫入 Header 可避免某些解壓工具(如 Windows 檔案總管)無法顯示檔案大小。
  • 大檔案:使用串流分塊讀寫,避免一次載入整個檔案到記憶體。
  • 中文檔名:SharpZipLib 4.2+ 內建 UTF-8 支援;舊版需設定 zipStream.UseZip64 = UseZip64.Off 並手動編碼。
  • 密碼保護:ZipInputStream.Password / ZipOutputStream.Password 僅支援傳統 ZipCrypto,非 AES-256。

結語

SharpZipLib API 直覺、效能優異,幾行程式碼即可完成壓縮/解壓縮核心需求。掌握 ZipOutputStream/ZipInputStream 串流模式,配合 using 確保資源釋放,即可輕鬆整合至任何 .NET 專案。

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