使用 Delphi 的 GZip 流压缩(可选 tar)

GZip stream compression with Delphi (optionally with tar)

我从几个小时开始就在搜索和搜索,以使用 Delphi 10.

中的流创建一个有效的 .tar.gz 文件

我能够使用 LibTar 解决 tarball 部分,效果很好。

经过一番搜索,我还找到了仅使用 System.ZLib 解压缩 gzip 数据的示例。秘密在于WindowBits参数:

// 31 bit wide window = gzip only mode
DecompStream:= TZDecompressionStream.Create(SourceStream, 15 + 16);
TarStream:= TTarArchive.Create(DecompStream);
TarStream.Reset;
while TarStream.FindNext(DirRec) do {...} TarStream.ReadFile(TargetStream);

太棒了!但是 System.ZLib 真的有可能解压缩 gzip(我猜只是忽略了那个 +16 的 gzip header 吗?),但不能自己创建这样的 header ?无论我尝试什么,我只得到一个无法用 7zip 或 WinRar 打开的文件,因为缺少 header。

可能就是行不通,因为gzip header里面有校验和,所以不知道后面的数据是不可能写header的。如何解决这个问题?编辑:这是错误的,请参阅评论:预告片中有 crc32。

似乎很多其他人也有这个问题 - 我发现并尝试了多种解决方案来添加这个 header,但没有任何效果,一切都需要添加长单位(不好但可以接受)甚至 DLL(我不能接受)。

秘密在于 WindowBits 参数 - 听起来很熟悉? :)

信不信由你,压缩到 gzip 的方式是一样的!我无法在任何地方使用 Google 或在 Embarcadero documentation/help 中找到它。但是看看 Delphi 东京的 System.ZLib 来源中的评论:

Add 16 to windowBits to write a simple gzip header and trailer around the compressed data instead of a zlib wrapper. The gzip header will have no file name, no extra data, no comment, no modification time (set to zero), no header crc, and the operating system will be set to 255 (unknown).

有效:

TargetStream:= TFileStream.Create(TargetFilename, fmCreate);
CompressStream:= TZCompressionStream.Create(TargetStream, zcDefault, 15 + 16);
TarStream:= TTarWriter.Create(CompressStream);
TarStream.AddStream(SourceStream1, SourceFilename1, Now);
TarStream.AddString(SourceString2, SourceFilename2, Now);