IRONSOFTWAREHOME

.NET 10中的异步Zip:一行创建或提取

.NET 10 中的一行代码创建或提取压缩

Tim Corey

~12m

通过System.IO.Compression,C#中的ZIP文件操作一直都是可行的,但每一次调用都是同步的,这意味着线程被阻塞,直到档案完全写入或读取完毕。 .NET 10通过一组异步重载改变了这一点,允许您创建、提取和填充Zip文件而不占用调用线程。

本演练基于Tim Corey最近的指南,演示了.NET 10中的新异步zip重载。我们将观察三种逐步详细的方法:一个用于构建档案的一行代码、一个用于解压它的单次调用,以及一个用于完全控制的手动方法,同时也会检查一个范围内的using陷阱。

设置:路径和源文件夹

[0:28 - 1:55] 设置开始于针对.NET 10的控制台应用程序和一个使用指令:

using System.IO.Compression;
C#

三个字符串变量定义了演示中使用的路径:

string sourceDirectory    = @"C:\temp\test";
string destinationZipFile = @"C:\temp\archive.zip";
string destinationDirectory = @"C:\temp\extracted";
C#

逐字字符串前缀(@)避免了反斜杠的重复。 destinationZipFile是将要创建的档案的完整路径。 destinationDirectory是提取内容后将落下的地方。

一个实用警告:不要将sourceDirectory内的路径。 将Zip文件写入正在压缩的文件夹中会导致打断过程的递归读取循环。

测试文件夹在根目录下包含两个文件,一个子文件夹内有第三个文件,这在探索includeBaseDirectory选项和手动方法中相对路径处理时很重要。

一行代码创建存档

[2:35 - 4:20] 异步创建调用是同步ZipFile.CreateFromDirectory的直接替代品:

await ZipFile.CreateFromDirectoryAsync(
    sourceDirectory,
    destinationZipFile,
    CompressionLevel.SmallestSize,
    includeBaseDirectory: false);
C#

CompressionLevel.Fastest则相反。 对于大多数开发场景,这种差异可以忽略不计,但对于同时处理多个存档的Web服务器,这种取舍是值得评估的。

false(默认),zip直接打开到文件。 传递test文件夹,实际文件位于其中。 大多数用例从将它设置为false中受益。

一行代码提取存档

[4:45 - 5:55] 提取遵循相同的模式:

await ZipFile.ExtractToDirectoryAsync(
    destinationZipFile,
    destinationDirectory,
    overwriteFiles: false);
C#

false,这在档案中的任何文件已存在于目标路径时,会抛出异常。 将其设置为true以静默替换现有文件。 运行两次解压说明了这一点:第一次通过并创建文件夹,而第二次则抛出异常,除非指定了overwriteFiles: true

选择性压缩:逐个添加文件

[6:15 - 9:50] 一行代码方法压缩整个目录而不进行过滤。 当您需要仅包含特定文件时,您可以使用FileStreamZipArchive手动构建档案:

await using FileStream zipStream = new FileStream(
    destinationZipFile,
    FileMode.Create,
    FileAccess.Write,
    FileShare.None,
    bufferSize: 4096,
    useAsync: true);

using ZipArchive archive = await ZipArchive.CreateAsync(
    zipStream,
    ZipArchiveMode.Create,
    leaveOpen: false,
    entryNameEncoding: null);
C#

这里的几个参数值得理解。 FileMode.Create覆盖该路径上任何现有文件。 相反,如果文件已存在,FileMode.CreateNew会抛出异常。 FileShare.None在档案写入的同时独占锁定文件,防止其他进程在操作过程中读取或写入。

FileStream上的useAsync: true在操作系统级别启用异步I/O。 请注意,如果未实际使用异步调用就设置此参数,可能会显著降低处理速度,有时甚至慢至十倍。 因为条目写入循环使用useAsync: true是此处的正确选择。 在同步代码路径上,将其留在默认的false

ZipArchive上的leaveOpen: false告诉它在被处理时关闭并刷新底层流。 entryNameEncoding: null保留默认编码,文档建议保留默认编码,除非有特定原因需要更改。

档案准备好后,提取源内容并写入每个条目。

string[] files = Directory.GetFiles(sourceDirectory, "*", SearchOption.AllDirectories);

foreach (string filePath in files)
{
    string relativePathAndName = Path.GetRelativePath(sourceDirectory, filePath);
    await archive.CreateEntryFromFileAsync(filePath, relativePathAndName);
}
C#

使用"</em>.txt"将限制档案仅包含文本文件,例如。

sourceDirectory的部分。 这就是在zip中作为条目名称存储的内容,忠实地再现了子文件夹层次结构。 如果您传递Path.GetFileName(filePath),每个条目无论原始位置如何都将落在zip根目录。 这样会产生一个扁平的档案,但如果两个条目在不同子文件夹中共享一个文件名,就有可能发生名称冲突。

作用范围内使用的陷阱

[9:50 - 11:30] 如果您尝试在手动zip块之后添加一个提取调用,将会遇到文件锁定异常:The process cannot access the file because it is being used by another process。 发生这种情况是因为zipStream上的using语句使用文件作用域语法,这意味着流在文件的末尾保持打开,而不是在zip块的括号处关闭。 提取尝试运行时,锁仍然被持有。

转换为大括号形式解决了这个问题。

// Before (file-scoped: stream stays open until end of file)
await using FileStream zipStream = new FileStream(...);

// After (block-scoped; stream released at the closing brace)
await using (FileStream zipStream = new FileStream(...))
{
    // zip operations here
}
// stream is now closed; extraction can proceed safely
C#

将zip工作包装在大括号中并移除尾随分号,会将流的生命周期限制在该明确的作用域内。 一旦执行离开闭合大括号,锁就被释放,后续的提取调用可以不冲突地打开相同的文件。

结论

[11:40 - end] 单行代码处理常见案例:用于存档整个文件夹的ExtractToDirectoryAsync。 当您需要控制哪些文件进入档案时,手动ZipArchive方法为您提供在条目级别的过滤、重命名和路径重写。

总结:添加ZipArchive路径。 如果流必须在后续代码运行之前释放,请使用大括号为您的using块设置作用域。 这些增改为.NET 10的完整zip工作流程提供了async/await模式。

观看完整的视频,在Tim Corey的YouTube频道上了解实时编码过程。

Earn More by Sharing What You Love

Do you create content for developers working with .NET, C#, Java, Python, or Node.js? Turn your expertise into extra income!

Let's Stay in Touch!

Join our newsletter, you’ll get exclusive access on article updates. We value your privacy

Key in blue circle

立即获取免费的 30 天试用版密钥

Your trial license will be sent to your email address

无任何限制。100% 解锁。无需信用卡。

bullet_checked无需信用卡或创建账户无任何限制。100% 解锁。无需信用卡。
  • Logo Aetna
  • Logo NASA
  • Logo GE
  • Logo Porsche
  • Logo USDA
  • Logo Qatar
Join Millions of Engineers who’ve tried IronPDF
获取您的无义务咨询
填写下面的表格或通过sales@ironsoftware.com
您的资料将始终保密。
深受全球数百万工程师信赖
Iron Software 的客户徽标
立即获取您的免费30 天试用密钥
无需信用卡或创建账户