当前位置: 首页 > news >正文

C# 压缩解压文件的常用方法

文章目录

  • C# 压缩解压文件的常用方法
    • 1. 使用 .NET 内置的 ZipFile 类
      • 压缩单个文件夹
      • 解压整个压缩包
      • 压缩单个文件
    • 2. 使用 ZipArchive 进行灵活操作
      • 压缩多个文件和文件夹
      • 解压(保留目录结构)
    • 3. 使用 SharpZipLib 库
      • 安装 SharpZipLib
      • 压缩多个文件和文件夹
      • 使用 SharpZipLib 解压
    • 4. 错误处理与最佳实践
    • 5. 方法对比与选择
  • 总结

C# 压缩解压文件的常用方法

在C#中处理文件和文件夹的压缩与解压,我们可使用微软内置的 System.IO.Compression 命名空间,也可选择功能更丰富的第三方库如 SharpZipLib。下面我将分别介绍几种常见方法,并提供处理多文件夹和文件混合压缩的方案。

1. 使用 .NET 内置的 ZipFile 类

.NET Framework 4.5 及以上版本和 .NET Core/.NET 5+ 提供了 ZipFile 类,适用于简单的压缩和解压场景。

压缩单个文件夹

using System.IO.Compression;public static void CompressDirectory(string sourceDirectoryName, string destinationArchiveFileName)
{ZipFile.CreateFromDirectory(sourceDirectoryName, destinationArchiveFileName, CompressionLevel.Optimal, false);
}

值得注意的是,使用ZipFile创建压缩包,默认不会包含根目录。如果需要包含根目录,可以先将文件夹复制到一个临时目录,然后压缩该临时目录。
例如,我对一个名为“Build a Large Language Model”的目录进行压缩,它里面包含了“doc”和“src”两个目录,压缩后的效果如下图:

示例截图

解压整个压缩包

public static void ExtractArchive(string sourceArchiveFileName, string destinationDirectoryName)
{ZipFile.ExtractToDirectory(sourceArchiveFileName, destinationDirectoryName);
}

压缩单个文件

压缩单个文件需要先创建临时目录,将文件复制进去后再压缩。

public static void CompressFile(string sourceFileName, string destinationArchiveFileName)
{string tempDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());Directory.CreateDirectory(tempDir);try{string destFile = Path.Combine(tempDir, Path.GetFileName(sourceFileName));File.Copy(sourceFileName, destFile);ZipFile.CreateFromDirectory(tempDir, destinationArchiveFileName, CompressionLevel.Optimal, false);}finally{Directory.Delete(tempDir, true);}
}

2. 使用 ZipArchive 进行灵活操作

ZipArchive 类提供了更精细的控制,适合混合压缩多个文件和文件夹。

压缩多个文件和文件夹

此方法递归地添加文件和文件夹,保持目录结构。

using System.IO.Compression;/// <summary>/// 压缩文件和文件夹到一个ZIP文件中/// </summary>/// <param name="zipPath">生成的压缩包路径</param>/// <param name="filesToZip">需要压缩的文件</param>/// <param name="foldersToZip">需要压缩的文件夹,默认没有</param>public static void CreateZipFile(string zipPath, string[]? filesToZip, string[]? foldersToZip = null, CompressionLevel compressionLevel = CompressionLevel.Optimal){using (FileStream zipStream = new FileStream(zipPath, FileMode.Create))using (ZipArchive archive = new ZipArchive(zipStream, ZipArchiveMode.Create)){// 添加单个文件if (filesToZip != null){foreach (string file in filesToZip){if (File.Exists(file)){string entryName = Path.GetFileName(file);archive.CreateEntryFromFile(file, entryName);}}}// 添加文件夹(递归)if (foldersToZip != null){foreach (string folder in foldersToZip){if (Directory.Exists(folder)){AddFolderToZip(archive, folder, Path.GetFileName(folder), compressionLevel);}}}}}/// <summary>/// 添加文件夹到ZIP归档中(递归)/// </summary>/// <param name="archive">ZIP压缩包</param>/// <param name="folderPath">文件夹路径</param>/// <param name="relativePath">相对路径</param>private static void AddFolderToZip(ZipArchive archive, string folderPath, string relativePath, CompressionLevel compressionLevel){string[] files = Directory.GetFiles(folderPath);foreach (string file in files){string entryName = Path.Combine(relativePath, Path.GetFileName(file));archive.CreateEntryFromFile(file, entryName);}string[] subfolders = Directory.GetDirectories(folderPath);foreach (string subfolder in subfolders){string newRelativePath = Path.Combine(relativePath, Path.GetFileName(subfolder));AddFolderToZip(archive, subfolder, newRelativePath, compressionLevel);}}

解压(保留目录结构)

public static void ExtractZipFile(string zipPath, string extractPath)
{using (ZipArchive archive = ZipFile.OpenRead(zipPath)){foreach (ZipArchiveEntry entry in archive.Entries){string fullPath = Path.Combine(extractPath, entry.FullName);string directory = Path.GetDirectoryName(fullPath);if (!Directory.Exists(directory))Directory.CreateDirectory(directory);if (!string.IsNullOrEmpty(entry.Name))entry.ExtractToFile(fullPath, overwrite: true);}}
}

3. 使用 SharpZipLib 库

对于更高级的需求(如加密、压缩级别控制、Unicode支持),可使用 SharpZipLib

安装 SharpZipLib

通过 NuGet 包管理器安装:

Install-Package SharpZipLib

压缩多个文件和文件夹

using ICSharpCode.SharpZipLib.Zip;public static void CreateZipWithSharpZipLib(string zipPath, string[] files, string[] folders, string password = null)
{using (ZipOutputStream zipStream = new ZipOutputStream(File.Create(zipPath))){zipStream.SetLevel(9); // 压缩级别 (0-9)if (!string.IsNullOrEmpty(password))zipStream.Password = password;byte[] buffer = new byte[4096];// 添加文件foreach (string file in files){if (File.Exists(file)){ZipEntry entry = new ZipEntry(Path.GetFileName(file));entry.DateTime = DateTime.Now;zipStream.PutNextEntry(entry);using (FileStream fs = File.OpenRead(file)){int sourceBytes;while ((sourceBytes = fs.Read(buffer, 0, buffer.Length)) > 0){zipStream.Write(buffer, 0, sourceBytes);}}zipStream.CloseEntry();}}// 添加文件夹foreach (string folder in folders){if (Directory.Exists(folder)){AddFolderToSharpZip(zipStream, folder, "", buffer);}}zipStream.Finish();}
}private static void AddFolderToSharpZip(ZipOutputStream zipStream, string folderPath, string relativePath, byte[] buffer)
{string[] files = Directory.GetFiles(folderPath);foreach (string file in files){string entryName = Path.Combine(relativePath, Path.GetFileName(file));ZipEntry entry = new ZipEntry(entryName);entry.DateTime = DateTime.Now;zipStream.PutNextEntry(entry);using (FileStream fs = File.OpenRead(file)){int sourceBytes;while ((sourceBytes = fs.Read(buffer, 0, buffer.Length)) > 0){zipStream.Write(buffer, 0, sourceBytes);}}zipStream.CloseEntry();}string[] subfolders = Directory.GetDirectories(folderPath);foreach (string subfolder in subfolders){string newRelativePath = Path.Combine(relativePath, Path.GetFileName(subfolder));AddFolderToSharpZip(zipStream, subfolder, newRelativePath, buffer);}
}

使用 SharpZipLib 解压

public static void ExtractWithSharpZipLib(string zipPath, string extractPath, string password = null)
{using (ZipInputStream zipStream = new ZipInputStream(File.OpenRead(zipPath))){zipStream.Password = password;ZipEntry entry;while ((entry = zipStream.GetNextEntry()) != null){string fullPath = Path.Combine(extractPath, entry.Name);string directory = Path.GetDirectoryName(fullPath);if (!Directory.Exists(directory))Directory.CreateDirectory(directory);if (!string.IsNullOrEmpty(entry.Name)){using (FileStream streamWriter = File.Create(fullPath)){byte[] data = new byte[4096];int size;while ((size = zipStream.Read(data, 0, data.Length)) > 0){streamWriter.Write(data, 0, size);}}}}}
}

4. 错误处理与最佳实践

进行压缩和解压操作时,务必添加错误处理。

try
{// 你的压缩或解压代码
}
catch (FileNotFoundException ex)
{Console.WriteLine($"文件未找到: {ex.Message}");
}
catch (DirectoryNotFoundException ex)
{Console.WriteLine($"目录未找到: {ex.Message}");
}
catch (IOException ex)
{Console.WriteLine($"IO错误: {ex.Message}");
}
catch (UnauthorizedAccessException ex)
{Console.WriteLine($"权限错误: {ex.Message}");
}
catch (Exception ex)
{Console.WriteLine($"未知错误: {ex.Message}");
}

5. 方法对比与选择

我们可以根据需求选择合适的方法:

方法特性ZipFile (内置)ZipArchive (内置)SharpZipLib (第三方)
易用性
功能丰富度基础中等高(加密、Unicode支持等)
性能良好良好良好
无需额外依赖
跨平台兼容性
推荐场景简单压缩/解压需精细控制复杂需求(如加密)

总结

在C#中实现zip压缩和解压,我们可根据需求选择:

  • 简单场景:使用内置的 ZipFile 类(ZipFile.CreateFromDirectoryZipFile.ExtractToDirectory)最方便。
  • 需精细控制或多文件/文件夹混合:使用 ZipArchive 类逐项添加内容更灵活。
  • 有高级需求(如加密、更高压缩比)SharpZipLib 等第三方库功能更强大。

处理多文件和文件夹时,递归添加是保持目录结构的关键。无论用哪种方法,都请注意添加适当的错误处理(如 try-catch 块)以确保程序健壮性。

http://www.dtcms.com/a/394736.html

相关文章:

  • .NET驾驭Word之力:打造专业文档 - 页面设置与打印控制完全指南
  • 为什么要创建音频地图?——探索Highcharts可视化的声音创新
  • Sass开发【四】
  • 从图片到实时摄像头:OpenCV EigenFace 人脸识别实战教程
  • kotlin 为什么要有协程作用域
  • MySQL二进制安装
  • 基于Java(SSH)+ Oracle 实现的(Web)视频教学平台
  • 西门子 S7-200 SMART PLC 结构化编程核心:子程序、中断程序与库概念详解
  • 树上LCA和树链剖分(未完待续)
  • 开发避坑指南(54):Mybatis plus查询指定的列
  • SQL注入可能用到的语句
  • 【论文阅读】GR00T N1:面向通用人形机器人的开放基础模型
  • 关于debian老系统安装软件失败的问题
  • ahooks:一套高质量、可靠的 React Hooks 库
  • 【一天一个Web3概念】Uniswap:去中心化金融(DeFi)的自动做市商革命
  • ROS2_YAML参数系统完整指南
  • day01电路基础
  • 贪心算法:以局部最优达成全局最优的艺术
  • Rancher学习
  • 华为认证HCIA备考:Vlan间通信,原理、三层交换机配置实验
  • 104、23种设计模式之访问者模式(13/23)
  • 什么是Mvcc
  • 如何在同一站点支持多版本的 reCAPTCHA 的兼容性方案
  • 管家预约字段修复说明
  • java面试day3 | 框架篇、Spring、SpringMVC、SpringBoot、MyBatis、注解、AOP、Bean
  • 【log4j2】log4j2插件挂载变更msg格式(工作实战,原理详解)
  • MVCC(多版本并发控制):InnoDB 高并发的核心技术
  • 决策树习题
  • PHP-ThinkPhp漏洞学习-MVC模型路由访问模版渲染安全写法版本漏洞(2024小迪安全Day31)
  • [已修复] iTunes 无法识别您的 iPhone