商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > c#如何解压zip文件_c#解压zip文件从入门到精通教程

c#如何解压zip文件_c#解压zip文件从入门到精通教程

  发布于2026-07-17 阅读(0)

扫一扫,手机访问

用 C# 解压 ZIP 文件,这事儿说简单也简单,说坑也不少。绝大多数场景下,直接上 System.IO.Compression.ZipFile 就足够了——从 .NET Framework 4.5 到 .NET Core 2.0 都原生支持,完全不用动辄引入第三方库来给自己加戏。

ZipFile.ExtractToDirectory 一键解压(推荐场景)

如果你的需求很标准——比如解压一个正常的 ZIP,目标目录不存在或者可以清空重来,而且不需要对里面的每个文件单独做手脚——那这招就是最省事的。

  • 一个关键前提:目标路径要么不存在,要么得是空目录。否则系统会直接给你甩一个 IOException,提示“目录非空”。这事儿在开发时很容易忽略。
  • ZIP 里的路径结构会被原封不动地还原。比如压缩包里有 project/src/Program.cs,解压后目标目录下就会自动建出 project/src/ 这个文件夹。你想跳过这些父目录?那这条路走不通。
  • 它不检查 ZIP 文件的完整性。如果压缩包本身坏了(比如下载时损坏),解压过程中会直接抛出 InvalidDataException。所以在解压前最好自己做一下基础校验,或者做好异常处理。
  • 来个最直白的例子:
    using System.IO.Compression;
    ZipFile.ExtractToDirectory(@"C:\data\archive.zip", @"C:\output");

ZipArchive 手动遍历解压(需要精细控制时)

什么时候才需要自己动手遍历?告诉你几个典型场景:你想跳过某些特定文件(比如 Mac 系统生成的那些烦人的 __MACOSX 文件夹),或者需要重命名条目、过滤扩展名、检查压缩方法、处理重复文件名,甚至要防范路径穿越攻击(恶意 ZIP 文件里可能夹着 ..\web.config 试图写到你不想让人写的地方)。这时候,ZipArchive 才是你的选择。

  • 路径安全是重中之重。一定要对 entry.FullName 做规范化和白名单校验,不然一个精心构造的 ZIP 就能在你的服务器上任意写文件。
  • entry.Length 是解压后的大小,entry.CompressedLength 是压缩后的大小。在解压前,你可以通过遍历一遍所有条目来预判一下磁盘空间够不够用,防止炸盘。
  • 调用 entry.Open() 返回的是一个 Stream,记得一定要用 using 包住它。这个小细节一旦忘了,文件句柄就会一直卡着,后续操作就会莫名其妙地失败。
  • 看一个带安全防护的示例(跳过 __MACOSX/ 开头的文件):
    using (var archive = ZipFile.OpenRead(@"C:\data\archive.zip"))
    {
        foreach (ZipArchiveEntry entry in archive.Entries)
        {
            if (entry.FullName.StartsWith("__MACOSX/", StringComparison.Ordinal)) continue;
            var destPath = Path.GetFullPath(Path.Combine(@"C:\output", entry.FullName));
            if (!destPath.StartsWith(@"C:\output\", StringComparison.Ordinal)) throw new SecurityException("Path escape detected");
            Directory.CreateDirectory(Path.GetDirectoryName(destPath));
            if (entry.Length > 0) // skip directories
            {
                entry.ExtractToFile(destPath, overwrite: true);
            }
        }
    }

常见报错和绕过方法

解压失败别慌,先看错误类型再对症下药,别动不动就想着换库重写。

  • NotSupportedException: No data is a vailable for encoding 936:这通常是 ZIP 文件名用了 GB2312 编码,而你的服务器没装中文语言包。解决方案有两个——要么改用 SharpZipLib 并指定 CodePage = 936,要么要求上游提供 UTF-8 编码的 ZIP 文件。
  • InvalidDataException: End of Central Directory record could not be found:八成是文件没下载完整。可以先用 File.ReadAllBytes 看看最后四个字节是不是 0x50 0x4B 0x05 0x06——这是 ZIP 格式的中央目录尾部标记。如果不是,说明文件有问题。
  • UnauthorizedAccessException:目标路径可能有只读属性或者权限不够。特别提醒,ExtractToFile 方法不会自动帮你清除只读标志,如果目标文件已存在且有只读属性,解压就会失败。可以预先调用 File.SetAttributes(path, FileAttributes.Normal) 处理一下。

真正棘手的——带密码的 ZIP、ZIP64 超大文件、分卷压缩包或者用了 LZMA 等非标准压缩算法的——System.IO.Compression 统统搞不定。这时候才需要评估引入 SharpZipLibDotNetZip。但别忘了,多数业务场景里的 ZIP 根本碰不上这些特性,别还没遇到问题就先给自己加了个大依赖。

本文转载于:https://www.php.cn/faq/2333855.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注