C#教程

关注公众号 jb51net

关闭
首页 > 软件编程 > C#教程 > C# 压缩格式

C# 各类压缩格式完整实现教程(ZIP 原生、7Z/rar/GZ 第三方)

作者:_Csharp

本文介绍了C#各类压缩格式完整实现教程(ZIP 原生、7Z/rar/GZ 第三方),本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友一起看看吧

C# 各类压缩格式完整实现教程(ZIP 原生、7Z/rar/GZ 第三方)

分两大块:

  1. 原生无依赖:System.IO.Compression 标准 ZIP(上位机首选,无需安装库) 支持:压缩、解压、遍历压缩包、删除包内文件、追加文件、分级目录打包、流压缩不落地
  2. 第三方库:7Z、RAR、GZIP、BZ2(SharpCompress,工业上位机通用) 支持 7z、rar、zip、tar、gz、bz2 全格式,单库统一 API,不用调用外部 exe

前置说明

一、.NET 原生内置 ZIP 操作(零 NuGet,推荐优先使用)

引用命名空间

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 整个文件夹递归打包(保留目录结构)

/// <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 读取压缩包内所有文件,不解压遍历信息

/// <summary>遍历压缩包内所有条目,获取名称、大小、修改时间</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 仅解压压缩包内指定单个文件(不解压全部)

/// <summary>提取压缩包内单个指定文件</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($"压缩包内不存在:{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 删除压缩包内指定文件(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 内存流压缩(不生成本地临时文件,上位机 HTTP 上传专用)

场景:文件读完直接压缩进 MemoryStream,直接上传网络,不落地磁盘

/// <summary>文件压缩到内存流,返回二进制</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 实现 7Z / RAR / GZ / BZ2 / TAR 全格式

1. 安装 NuGet

Install-Package SharpCompress

支持格式:

命名空间

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 压缩(创建.7z 文件)

/// <summary>创建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 文件解压(仅支持读取,无法创建 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 统一压缩入口(兼容 zip/7z)

/// <summary>通用打包,根据后缀自动选择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 创建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");
    }
}

三、上位机高频业务封装综合工具类(整合原生 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 原生支持压缩率优点上位机适用场景
ZIP✅ 内置中等无第三方库、跨平台、读写快批量图片 / CSV 上传、日常打包
7Z❌需 SharpCompress极高压缩体积最小,适合大量日志每天上百张截图、长期数据归档
RAR❌仅解压,不能创建老旧归档文件读取读取客户发来的 rar 报表,不推荐生成
GZIP✅内置单文件轻量化,网络传输单条日志、单个 CSV 单独压缩上传

五、上位机开发常见坑

  1. 原生 Zip 不支持加密、分卷 加密压缩包用 7z + SharpCompress;分卷 7z 也支持。
  2. RAR 无法创建 RAR 算法专利闭源,任何 C# 库都不能生成 rar,只能解压;需要生成 rar 只能调用WinRAR.exe进程。
  3. 压缩大文件 UI 卡死 全部打包逻辑丢Task.Run异步执行,配合进度流可扩展进度回调。
  4. 中文乱码 SharpCompress 默认 UTF8;原生 ZipArchive .NET Core/.NET5 + 自动支持中文,.NET Framework 需设置编码。
  5. 压缩后直接 HTTP 上传 使用内存流模式,无需生成本地临时压缩包,减少磁盘 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));
    }
}

到此这篇关于C# 各类压缩格式完整实现教程(ZIP 原生、7Z/rar/GZ 第三方)的文章就介绍到这了,更多相关C# 压缩格式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文