.net 7+ 及以上版本的 system.io.compression 命名空间中确实不存在 tararchive、tarentry 等原生 api,官方仅内置 gzipstream 和 brotlistream;需使用 sharpcompress 库或调用系统 tar 命令实现 tar 处理。

System.IO.Compression.TarArchive 不存在,别白找
NET 7+ 里没有 TarArchive 类,也没有 TarEntry 或类似原生 API。官方只内置了 GZipStream 和 BrotliStream,Tar 格式完全没进 BCL。你搜到的任何“TarArchive.Create”都是假的,要么是第三方库包装的,要么是文档写错了。
常见错误现象:TypeNotFoundException 报 TarArchive 找不到;IntelliSense 不提示;NuGet 包引用后仍编译失败。
- 别在
System.IO.Compression命名空间下翻了,它真没这个类 - 别信 .NET SDK 文档里混进来的旧社区 PR 描述,那些没合并
- 如果你刚升级到 .NET 8 并期待“终于原生支持 tar”,那得失望了
用 SharpCompress 是目前最稳的方案
SharpCompress 是当前兼容性最好、维护活跃、API 清晰的 tar 处理库,支持 .NET 6+,且对流式读写、大文件、长路径、稀疏文件等场景处理得比老库(如 DotNetZip)更靠谱。
使用场景:需要创建 tar 包(不压缩)、解压 tar 包(不带 gzip)、或组合 .tar.gz(先 tar 再 gzip)。
- 安装:
dotnet add package SharpCompress - 创建 tar:
WriterOptions必须设VolumeName为空或显式指定,否则某些 tar 工具(如 Linuxtar)会报 “invalid header” - 解压时注意
ArchiveReader默认不自动展开目录结构,需手动调用entry.WriteToDirectory并传入new ExtractionOptions { ExtractFullPath = true } - 性能影响:SharpCompress 默认启用缓冲(
Buffering = true),对小文件略慢但更安全;大文件可关掉缓冲提升吞吐
示例(创建 tar):
using (var archive = new TarArchiveWriter("out.tar", new WriterOptions(SharpCompress.Common.ArchiveEncoding.Utf8)))
{
archive.Write("README.md", File.OpenRead("README.md"));
archive.Write("src/", new DirectoryInfo("src")); // 递归加目录
}想“纯原生”?只能手撸或降级用 Process 调 tar 命令
Windows 10 1809+ / Windows 11 自带 tar.exe,Linux/macOS 更不用说。如果部署环境可控,用 Process.Start 调系统命令反而是最轻量、最符合 POSIX 行为的方式。
容易踩的坑:
-
tar -cf创建时若路径含空格,必须用双引号包裹参数,且ProcessStartInfo.ArgumentList在 .NET 5+ 才安全,旧版要用Arguments字符串拼接(易被注入) - Windows 上
tar.exe对中文路径默认用 GBK,而 C#File.ReadAllText默认 UTF-8,解包后文件名乱码——必须加--format=posix和--encoding=UTF-8 - 错误信息捕获:别只看
ExitCode,要读StandardError流,否则tar: Cannot open: No such file or directory这类关键报错会被吞掉
示例(解压):
var psi = new ProcessStartInfo("tar", "-xf archive.tar -C ./output")
{
UseShellExecute = false,
RedirectStandardError = true,
CreateNoWindow = true
};
using var p = Process.Start(psi);
p.WaitForExit();
if (p.ExitCode != 0)
throw new IOException(await p.StandardError.ReadToEndAsync());gzip + tar 组合不是“tar.gz 解压”,而是两层流嵌套
很多人以为 .tar.gz 是一种格式,其实它是两个独立步骤:先用 tar 打包(无压缩),再用 gzip 压缩整个 tar 流。解压时也必须反向:先 GZipStream 解压,再喂给 tar reader。
SharpCompress 支持自动识别 .tar.gz,但底层仍是两层——这意味着你不能指望 GZipStream 直接吐出 tar 文件头;也不能把未解压的 .tar.gz 流直接塞给 TarArchiveReader。
- 手动组合示例:用
new GZipStream(fileStream, CompressionMode.Decompress)包一层,再传给TarArchiveReader.Open(gzipStream) - 兼容性注意:某些老旧 tar.gz 用的是
zlib而非标准 gzip,SharpCompress 默认不支持,得换ZLibStream(需额外引用System.IO.Compression.ZLib) - 性能影响:嵌套流会多一次内存拷贝,大数据量建议用
Span<byte></byte>缓冲池复用,而非每次都 new byte[8192]
真正麻烦的不是“怎么写”,而是 tar 格式本身没统一标准:GNU tar、POSIX ustar、pax 扩展、长路径编码方式……不同工具生成的包,可能在另一个平台打不开。选 SharpCompress 至少能覆盖主流变体,但别指望它能 100% 兼容所有边缘 case。










