C# 各類壓縮格式完整實現(xiàn)教程(ZIP 原生、7Z/rar/GZ 第三方)
C# 各類壓縮格式完整實現(xiàn)教程(ZIP 原生、7Z/rar/GZ 第三方)
分兩大塊:
- 原生無依賴:System.IO.Compression 標準 ZIP(上位機首選,無需安裝庫) 支持:壓縮、解壓、遍歷壓縮包、刪除包內(nèi)文件、追加文件、分級目錄打包、流壓縮不落地
- 第三方庫:7Z、RAR、GZIP、BZ2(SharpCompress,工業(yè)上位機通用) 支持 7z、rar、zip、tar、gz、bz2 全格式,單庫統(tǒng)一 API,不用調(diào)用外部 exe
前置說明
- 純.NET 自帶
ZipFile/ZipArchive僅支持標準 ZIP,不支持 7z、rar; - 要 7z/rar 必須用
SharpCompressNuGet 包(輕量、無依賴、純托管); - 上位機場景:批量日志 CSV、圖片、報表打包,超大文件分卷壓縮、后臺異步壓縮。
一、.NET 原生內(nèi)置 ZIP 操作(零 NuGet,推薦優(yōu)先使用)
引用命名空間
using System; using System.IO; using System.IO.Compression; using System.Collections.Generic;
1. 常用枚舉:壓縮等級
// CompressionLevel // Optimal:平衡壓縮率與速度(上位機默認) // Fastest:快速壓縮,體積大 // NoCompression:僅打包不壓縮
1.1 多個文件打包成 ZIP(文件列表)
/// <summary>多文件打包ZIP</summary>
/// <param name="sourceFiles">本地文件完整路徑集合</param>
/// <param name="zipSavePath">輸出壓縮包路徑</param>
/// <param name="level">壓縮等級</param>
public static void CreateZipByFiles(List<string> sourceFiles, string zipSavePath, CompressionLevel level = CompressionLevel.Optimal)
{
if (File.Exists(zipSavePath)) File.Delete(zipSavePath);
using var zip = ZipFile.Open(zipSavePath, ZipArchiveMode.Create);
foreach (var file in sourceFiles)
{
if (!File.Exists(file)) continue;
string fileName = Path.GetFileName(file);
// 將文件寫入壓縮包根目錄
zip.CreateEntryFromFile(file, fileName, level);
}
}1.2 整個文件夾遞歸打包(保留目錄結(jié)構(gòu))
/// <summary>整文件夾打包,保留子目錄層級</summary>
public static void CreateZipByFolder(string sourceFolder, string zipSavePath, CompressionLevel level = CompressionLevel.Optimal)
{
if (File.Exists(zipSavePath)) File.Delete(zipSavePath);
ZipFile.CreateFromDirectory(sourceFolder, zipSavePath, level, includeBaseDirectory: true);
}1.3 解壓整個 ZIP 到目錄
/// <summary>完整解壓ZIP</summary>
public static void ExtractZip(string zipPath, string targetDir, bool overwrite = true)
{
if (!Directory.Exists(targetDir)) Directory.CreateDirectory(targetDir);
ZipFile.ExtractToDirectory(zipPath, targetDir, overwrite);
}1.4 讀取壓縮包內(nèi)所有文件,不解壓遍歷信息
/// <summary>遍歷壓縮包內(nèi)所有條目,獲取名稱、大小、修改時間</summary>
public static List<ZipEntryInfo> ReadZipEntryList(string zipPath)
{
var list = new List<ZipEntryInfo>();
using var zip = ZipFile.OpenRead(zipPath);
foreach (var entry in zip.Entries)
{
list.Add(new ZipEntryInfo
{
EntryName = entry.FullName,
Length = entry.Length,
LastWriteTime = entry.LastWriteTime,
IsDirectory = entry.FullName.EndsWith("/")
});
}
return list;
}
// 條目信息實體
public class ZipEntryInfo
{
public string EntryName { get; set; }
public long Length { get; set; }
public DateTimeOffset LastWriteTime { get; set; }
public bool IsDirectory { get; set; }
}1.5 僅解壓壓縮包內(nèi)指定單個文件(不解壓全部)
/// <summary>提取壓縮包內(nèi)單個指定文件</summary>
public static void ExtractSingleFileFromZip(string zipPath, string entryName, string saveFilePath)
{
using var zip = ZipFile.OpenRead(zipPath);
var entry = zip.GetEntry(entryName);
if (entry == null) throw new Exception($"壓縮包內(nèi)不存在:{entryName}");
using var entryStream = entry.Open();
using var fileStream = new FileStream(saveFilePath, FileMode.Create);
entryStream.CopyTo(fileStream);
}1.6 向已存在的 ZIP 追加新文件(增量打包)
/// <summary>打開已有壓縮包,追加文件</summary>
public static void AddFileToExistZip(string zipPath, string addFile, string entryName, CompressionLevel level = CompressionLevel.Optimal)
{
if (!File.Exists(zipPath)) throw new FileNotFoundException("壓縮包不存在");
using var zip = ZipFile.Open(zipPath, ZipArchiveMode.Update);
// 同名文件會覆蓋
zip.CreateEntryFromFile(addFile, entryName, level);
}1.7 刪除壓縮包內(nèi)指定文件(Update 模式)
public static void DeleteEntryInZip(string zipPath, string entryName)
{
using var zip = ZipFile.Open(zipPath, ZipArchiveMode.Update);
var entry = zip.GetEntry(entryName);
if (entry != null) entry.Delete();
}1.8 內(nèi)存流壓縮(不生成本地臨時文件,上位機 HTTP 上傳專用)
場景:文件讀完直接壓縮進 MemoryStream,直接上傳網(wǎng)絡(luò),不落地磁盤
/// <summary>文件壓縮到內(nèi)存流,返回二進制</summary>
public static byte[] ZipFileToMemory(string filePath)
{
using var ms = new MemoryStream();
using var zip = new ZipArchive(ms, ZipArchiveMode.Create, leaveOpen: true);
string fileName = Path.GetFileName(filePath);
var entry = zip.CreateEntry(fileName, CompressionLevel.Optimal);
using var entryStream = entry.Open();
using var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
fs.CopyTo(entryStream);
ms.Position = 0;
return ms.ToArray();
}1.9 異步壓縮(UI 不卡頓,WinForm/WPF 上位機)
public static async Task CreateZipAsync(List<string> files, string zipPath)
{
await Task.Run(() =>
{
CreateZipByFiles(files, zipPath);
});
}二、SharpCompress 實現(xiàn) 7Z / RAR / GZ / BZ2 / TAR 全格式
1. 安裝 NuGet
Install-Package SharpCompress
支持格式:
- 寫:Zip, 7Zip, GZip, BZip2, Tar
- 讀:Rar5, Rar4, 7z, zip, gz, bz2, tar
命名空間
using SharpCompress.Archives; using SharpCompress.Archives.SevenZip; using SharpCompress.Archives.Zip; using SharpCompress.Common; using SharpCompress.Writers; using SharpCompress.Writers.Zip; using System.IO; using System.Collections.Generic;
2. 7Z 壓縮(創(chuàng)建.7z 文件)
/// <summary>創(chuàng)建7z壓縮包</summary>
public static void Create7zArchive(List<string> sourceFiles, string sevenZipPath)
{
if (File.Exists(sevenZipPath)) File.Delete(sevenZipPath);
using var archive = SevenZipArchive.Create(sevenZipPath);
foreach (var file in sourceFiles)
{
if (!File.Exists(file)) continue;
string entryName = Path.GetFileName(file);
archive.AddEntry(entryName, file);
}
archive.Save();
}3. 7Z 完整解壓
public static void Extract7z(string sevenZipPath, string targetDir)
{
if (!Directory.Exists(targetDir)) Directory.CreateDirectory(targetDir);
using var archive = SevenZipArchive.Open(sevenZipPath);
foreach (var entry in archive.Entries)
{
if (!entry.IsDirectory)
{
entry.WriteToDirectory(targetDir, new ExtractionOptions
{
ExtractFullPath = true,
Overwrite = true
});
}
}
}4. RAR 文件解壓(僅支持讀取,無法創(chuàng)建 rar,rar 為閉源格式)
/// <summary>解壓RAR4/RAR5</summary>
public static void ExtractRar(string rarPath, string targetDir)
{
if (!Directory.Exists(targetDir)) Directory.CreateDirectory(targetDir);
using var archive = ArchiveFactory.Open(rarPath);
foreach (var entry in archive.Entries)
{
if (!entry.IsDirectory)
{
entry.WriteToDirectory(targetDir, new ExtractionOptions { ExtractFullPath = true, Overwrite = true });
}
}
}5. GZIP 單文件壓縮(日志、CSV 常用)
/// <summary>單個文件gzip壓縮</summary>
public static void CreateGzip(string sourceFile, string gzSavePath)
{
using var fsOut = File.Create(gzSavePath);
using var gzStream = new GZipStream(fsOut, CompressionMode.Compress);
using var fsIn = File.OpenRead(sourceFile);
fsIn.CopyTo(gzStream);
}
/// <summary>解壓gz</summary>
public static void ExtractGzip(string gzPath, string outFile)
{
using var fsIn = File.OpenRead(gzPath);
using var gzStream = new GZipStream(fsIn, CompressionMode.Decompress);
using var fsOut = File.Create(outFile);
gzStream.CopyTo(fsOut);
}6. SharpCompress 統(tǒng)一壓縮入口(兼容 zip/7z)
/// <summary>通用打包,根據(jù)后綴自動選擇7z/zip</summary>
public static void CreateMultiFormatArchive(List<string> files, string outPath)
{
string ext = Path.GetExtension(outPath).ToLower();
if (ext == ".7z")
{
Create7zArchive(files, outPath);
}
else if (ext == ".zip")
{
// SharpCompress 創(chuàng)建zip
var writerOpt = new ZipWriterOptions(CompressionType.Deflate);
using var stream = File.Create(outPath);
using var writer = new ZipWriter(stream, writerOpt);
foreach (var f in files)
{
writer.Write(Path.GetFileName(f), File.OpenRead(f));
}
}
else
{
throw new NotSupportedException("僅支持zip/7z");
}
}三、上位機高頻業(yè)務(wù)封裝綜合工具類(整合原生 ZIP + 7Z/GZ)
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using SharpCompress.Archives;
using SharpCompress.Archives.SevenZip;
using SharpCompress.Common;
public static class ArchiveHelper
{
#region 原生ZIP
/// <summary>多文件打包標準ZIP</summary>
public static void ZipFiles(List<string> files, string zipPath, CompressionLevel level = CompressionLevel.Optimal)
{
if (File.Exists(zipPath)) File.Delete(zipPath);
using var zip = ZipFile.Open(zipPath, ZipArchiveMode.Create);
foreach (var f in files)
{
if (File.Exists(f)) zip.CreateEntryFromFile(f, Path.GetFileName(f), level);
}
}
public static void UnZip(string zipPath, string destDir, bool overwrite = true)
{
if (!Directory.Exists(destDir)) Directory.CreateDirectory(destDir);
ZipFile.ExtractToDirectory(zipPath, destDir, overwrite);
}
#endregion
#region 7Z 壓縮解壓
public static void Compress7z(List<string> files, string sevenZipPath)
{
if (File.Exists(sevenZipPath)) File.Delete(sevenZipPath);
using var archive = SevenZipArchive.Create(sevenZipPath);
foreach (var f in files)
{
if (File.Exists(f)) archive.AddEntry(Path.GetFileName(f), f);
}
archive.Save();
}
public static void Extract7z(string sevenZipPath, string destDir)
{
if (!Directory.Exists(destDir)) Directory.CreateDirectory(destDir);
using var archive = SevenZipArchive.Open(sevenZipPath);
foreach (var entry in archive.Entries)
{
if (!entry.IsDirectory)
entry.WriteToDirectory(destDir, new ExtractionOptions { ExtractFullPath = true, Overwrite = true });
}
}
#endregion
#region RAR解壓(只讀)
public static void ExtractRar(string rarPath, string destDir)
{
if (!Directory.Exists(destDir)) Directory.CreateDirectory(destDir);
using var archive = ArchiveFactory.Open(rarPath);
foreach (var entry in archive.Entries)
{
if (!entry.IsDirectory)
entry.WriteToDirectory(destDir, new ExtractionOptions { ExtractFullPath = true, Overwrite = true });
}
}
#endregion
#region GZIP單文件
public static void GzipCompress(string source, string gzOut)
{
using var outStream = File.Create(gzOut);
using var gz = new GZipStream(outStream, CompressionMode.Compress);
using var inStream = File.OpenRead(source);
inStream.CopyTo(gz);
}
public static void GzipDecompress(string gzFile, string outputFile)
{
using var inStream = File.OpenRead(gzFile);
using var gz = new GZipStream(inStream, CompressionMode.Decompress);
using var outStream = File.Create(outputFile);
gz.CopyTo(outStream);
}
#endregion
#region 異步打包(UI不卡死)
public static async Task ZipFilesAsync(List<string> files, string zipPath)
{
await Task.Run(() => ZipFiles(files, zipPath));
}
public static async Task Compress7zAsync(List<string> files, string sevenZipPath)
{
await Task.Run(() => Compress7z(files, sevenZipPath));
}
#endregion
}四、各格式對比(上位機選型建議)
表格
| 格式 | .NET 原生支持 | 壓縮率 | 優(yōu)點 | 上位機適用場景 |
|---|---|---|---|---|
| ZIP | ? 內(nèi)置 | 中等 | 無第三方庫、跨平臺、讀寫快 | 批量圖片 / CSV 上傳、日常打包 |
| 7Z | ?需 SharpCompress | 極高 | 壓縮體積最小,適合大量日志 | 每天上百張截圖、長期數(shù)據(jù)歸檔 |
| RAR | ?僅解壓,不能創(chuàng)建 | 高 | 老舊歸檔文件讀取 | 讀取客戶發(fā)來的 rar 報表,不推薦生成 |
| GZIP | ?內(nèi)置 | 高 | 單文件輕量化,網(wǎng)絡(luò)傳輸 | 單條日志、單個 CSV 單獨壓縮上傳 |
五、上位機開發(fā)常見坑
- 原生 Zip 不支持加密、分卷 加密壓縮包用 7z + SharpCompress;分卷 7z 也支持。
- RAR 無法創(chuàng)建 RAR 算法專利閉源,任何 C# 庫都不能生成 rar,只能解壓;需要生成 rar 只能調(diào)用
WinRAR.exe進程。 - 壓縮大文件 UI 卡死 全部打包邏輯丟
Task.Run異步執(zhí)行,配合進度流可擴展進度回調(diào)。 - 中文亂碼 SharpCompress 默認 UTF8;原生 ZipArchive .NET Core/.NET5 + 自動支持中文,.NET Framework 需設(shè)置編碼。
- 壓縮后直接 HTTP 上傳 使用內(nèi)存流模式,無需生成本地臨時壓縮包,減少磁盤 IO。
六、擴展:加密 7Z 壓縮包(帶密碼)
/// <summary>加密7z壓縮包</summary>
public static void CreateEncrypt7z(List<string> files, string sevenZipPath, string password)
{
if (File.Exists(sevenZipPath)) File.Delete(sevenZipPath);
var opt = new SevenZipWriterOptions
{
Password = password,
EncryptFileName = true // 加密文件名
};
using var stream = File.Create(sevenZipPath);
using var writer = new SevenZipWriter(stream, opt);
foreach (var f in files)
{
writer.Write(Path.GetFileName(f), File.OpenRead(f));
}
}到此這篇關(guān)于C# 各類壓縮格式完整實現(xiàn)教程(ZIP 原生、7Z/rar/GZ 第三方)的文章就介紹到這了,更多相關(guān)C# 壓縮格式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
DevExpress實現(xiàn)自定義GridControl中按鈕文字內(nèi)容的方法
這篇文章主要介紹了DevExpress實現(xiàn)自定義GridControl中按鈕文字內(nèi)容的方法,需要的朋友可以參考下2014-08-08
基于C#實現(xiàn)桌面應(yīng)用程序開機自啟動功能
許多桌面應(yīng)用程序開發(fā)中,開機自啟動是一個常見需求,例如殺毒軟件、系統(tǒng)工具、監(jiān)控程序等,通常都希望能夠在操作系統(tǒng)啟動時自動運行,本文將以一個實際案例為基礎(chǔ),詳細講解如何通過 配置文件控制是否啟用開機自啟動功能,需要的朋友可以參考下2025-06-06
C# TreeView 控件的詳解與應(yīng)用小結(jié)
本文主要介紹了C# TreeView 控件,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2026-01-01
詳解WPF如何顯示具有層級關(guān)系的數(shù)據(jù)
這篇文章主要為大家詳細介紹了在WPF中如何顯示具有層級關(guān)系的數(shù)據(jù),文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下2024-04-04
C#?NLua?Winform實現(xiàn)熱更新的項目實踐
本文介紹了在.NET應(yīng)用中使用NLua庫嵌入Lua腳本,實現(xiàn)動態(tài)邏輯和熱更新功能,包括創(chuàng)建項目、設(shè)置公共數(shù)據(jù)、Lua腳本交互以及熱更新的具體實現(xiàn)步驟,感興趣的可以了解一下2025-11-11

