public static void ExtractTar(Stream stream, string outputDir)
{
var buffer = new byte[100];
while (true)
{
stream.Read(buffer, 0, 100);
var name = Encoding.ASCII.GetString(buffer).Trim('\0');
if (String.IsNullOrWhiteSpace(name))
break;
stream.Seek(24, SeekOrigin.Current);
stream.Read(buffer, 0, 12);
var size = Convert.ToInt64(Encoding.ASCII.GetString(buffer, 0, 12).Trim(), 8);
stream.Seek(376L, SeekOrigin.Current);
var output = Path.Combine(outputDir, name);
if (!Directory.Exists(Path.GetDirectoryName(output)))
Directory.CreateDirectory(Path.GetDirectoryName(output));
using (var str = File.Open(output, FileMode.OpenOrCreate, FileAccess.Write))
{
var buf = new byte[size];
stream.Read(buf, 0, buf.Length);
str.Write(buf, 0, buf.Length);
}
var pos = stream.Position;
var offset = 512 - (pos % 512);
if (offset == 512)
offset = 0;
stream.Seek(offset, SeekOrigin.Current);
}
}
这里有一些帮助函数,用于从文件打开,并在提取之前自动首先解压缩tar.gz文件/流。
public static void ExtractTarGz(string filename, string outputDir)
{
using (var stream = File.OpenRead(filename))
ExtractTarGz(stream, outputDir);
}
public static void ExtractTarGz(Stream stream, string outputDir)
{
// A GZipStream is not seekable, so copy it first to a MemoryStream
using (var gzip = new GZipStream(stream, CompressionMode.Decompress))
{
const int chunk = 4096;
using (var memStr = new MemoryStream())
{
int read;
var buffer = new byte[chunk];
do
{
read = gzip.Read(buffer, 0, chunk);
memStr.Write(buffer, 0, read);
} while (read == chunk);
memStr.Seek(0, SeekOrigin.Begin);
ExtractTar(memStr, outputDir);
}
}
}
public static void ExtractTar(string filename, string outputDir)
{
using (var stream = File.OpenRead(filename))
ExtractTar(stream, outputDir);
}
在. NET中有两种压缩/解压缩的方法,首先你可以使用Gzipstream类和DeflatStream都可以将你的文件压缩成. gz格式,所以如果你在Gzipstream中压缩了任何文件,它可以用任何流行的压缩应用程序打开,如winzip/winrar,7zip,但你不能用DeflatStream打开压缩文件。这两个类来自. NET 2。 还有另一种方法是Package类,它实际上与Gzipstream和DeflatStream相同,唯一不同的是你可以压缩多个文件,然后可以用winzip/winrar打开,www.example.com就是. NET的全部。7zip.so如果你解压缩任何带有包类docx文件,你可以看到里面存储的所有东西。所以不要使用. NET库进行压缩或解压缩,因为您甚至不能生成通用压缩文件或解压缩通用zip文件。您必须考虑使用第三方库,例如http://www.icsharpcode.net/OpenSource/SharpZipLib/ so don't use .NET libraries for compressing or even decompressing cause you can't even make a generic compress file or even decompress a generic zip file. you have to consider for a third party library such as http://www.icsharpcode.net/OpenSource/SharpZipLib/ 或者从底层开始执行所有的事情。
await using var tarStream = new FileStream(tarFilePath, new FileStreamOptions { Mode = FileMode.Open, Access = FileAccess.Read, Options = FileOptions.Asynchronous });
await using var tarReader = new TarReader(tarStream);
TarEntry entry;
while ((entry = await tarReader.GetNextEntryAsync()) != null)
{
if (entry.EntryType is TarEntryType.SymbolicLink or TarEntryType.HardLink or TarEntryType.GlobalExtendedAttributes)
{
continue;
}
Console.WriteLine($"Extracting {entry.Name}");
await entry.ExtractToFileAsync(Path.Join(outputDirectory, entry.Name));
}
6条答案
按热度按时间w3nuxt5m1#
在寻找同一个问题的快速答案时,我遇到了这个线程,并且对当前的答案并不完全满意,因为它们都指向使用第三方依赖项到更大的库,所有这些都只是为了实现将
tar.gz
文件简单提取到磁盘。虽然
gz
可能被认为相当复杂,但tar
却相当简单。在其核心,它只需要一堆文件,为每个描述文件的文件添加一个500字节的头(但需要512字节),并将它们全部写入512字节对齐的单个存档。没有压缩,通常通过将创建的文件压缩到gz
存档来处理,.NET内置了这个存档,它可以处理所有困难的部分。在查看了
tar
的spec之后,我们只需要从头文件中挑选出2个值(特别是在Windows上),以便从流中提取文件。第一个是name
,第二个是size
。使用这两个值,我们只需要查找流中的适当位置并将字节复制到文件中。我做了一个非常基本的、低级的方法来将
tar
归档文件提取到目录中,并添加了一些帮助函数,用于从流或文件名打开,并首先使用内置函数解压缩gz
文件。主要的方法是这样的:
这里有一些帮助函数,用于从文件打开,并在提取之前自动首先解压缩
tar.gz
文件/流。下面是完整文件的gist和一些注解。
s6fujrry2#
Tar-cs将完成这项工作,但它相当慢。我建议使用SharpCompress,它的速度要快得多。它还支持其他压缩类型,并且最近已更新。
vwkv1x7d3#
参见tar-cs
mklgxw1f4#
由于不允许使用外部库,因此您也不限于
tar
文件的特定格式。事实上,他们甚至不需要将所有内容都放在同一个文件中。您可以用C#编写自己的tar类实用程序,它遍历目录树并生成两个文件:一个“头”文件,由一个序列化的字典组成,将
System.IO.Path
示例Map到偏移量/长度对,以及一个大文件,包含连接成一个巨大blob的各个文件的内容。这不是一个微不足道的任务,但也不是过于复杂。vuktfyat5#
在. NET中有两种压缩/解压缩的方法,首先你可以使用Gzipstream类和DeflatStream都可以将你的文件压缩成. gz格式,所以如果你在Gzipstream中压缩了任何文件,它可以用任何流行的压缩应用程序打开,如winzip/winrar,7zip,但你不能用DeflatStream打开压缩文件。这两个类来自. NET 2。
还有另一种方法是Package类,它实际上与Gzipstream和DeflatStream相同,唯一不同的是你可以压缩多个文件,然后可以用winzip/winrar打开,www.example.com就是. NET的全部。7zip.so如果你解压缩任何带有包类docx文件,你可以看到里面存储的所有东西。所以不要使用. NET库进行压缩或解压缩,因为您甚至不能生成通用压缩文件或解压缩通用zip文件。您必须考虑使用第三方库,例如http://www.icsharpcode.net/OpenSource/SharpZipLib/ so don't use .NET libraries for compressing or even decompressing cause you can't even make a generic compress file or even decompress a generic zip file. you have to consider for a third party library such as http://www.icsharpcode.net/OpenSource/SharpZipLib/
或者从底层开始执行所有的事情。
cyvaqqii6#
.NET 7添加了几个类来处理TAR文件:
提取到目录:
枚举TAR文件并手动提取其条目: