Compression 从单独压缩的块创建gzip流

Compression 从单独压缩的块创建gzip流,compression,gzip,zlib,Compression,Gzip,Zlib,我希望能够使用并发CPU线程生成gzip(.gz)文件。也就是说,我将使用单独初始化的z_流记录从输入文件中压缩单独的块 在经典的单线程操作中,zlib的inflate()函数应该可以读取生成的文件 可能吗?即使它需要定制的zlib代码?唯一的要求是,目前存在的zlib的充气代码可以处理它 更新 源代码演示了它是如何工作的。它使用一些复杂的优化在块之间共享字典,从而保持最佳的压缩率。如果使用较新的zlib版本,它将进一步处理位打包 然而,我喜欢了解如何在不使用优化pigz的情况下实现自己的功能,

我希望能够使用并发CPU线程生成gzip(.gz)文件。也就是说,我将使用单独初始化的
z_流
记录从输入文件中压缩单独的块

在经典的单线程操作中,zlib的inflate()函数应该可以读取生成的文件

可能吗?即使它需要定制的zlib代码?唯一的要求是,目前存在的zlib的充气代码可以处理它

更新

源代码演示了它是如何工作的。它使用一些复杂的优化在块之间共享字典,从而保持最佳的压缩率。如果使用较新的zlib版本,它将进一步处理位打包

然而,我喜欢了解如何在不使用优化
pigz
的情况下实现自己的功能,保持简单

虽然很多人认为源代码是最终的文档(),但我宁愿用简单的语言来解释,以避免误解。(虽然文档实际上很好地描述了发生的事情,但它们并没有很好地解释需要做些什么才能实现自己的目标。)

通过浏览代码,到目前为止我发现了很多:

似乎只是使用
deflate(…,Z_SYNC\u FLUSH)
而不是使用
Z_FINISH
创建每个压缩块。但是,
deflateEnd()
会给出一个错误,不确定是否可以忽略该错误。需要手动计算所有块的最终校验和,尽管我想知道如何在最后添加校验和。还有一个相当复杂的
put_traile()
函数用于编写gzip头-我想知道zlib自己的代码是否也可以处理简单的情况

如有任何澄清,我们将不胜感激

另外,我意识到,为了将多线程压缩文件写入zip归档文件,我应该以同样的方式询问如何编写zlib流。我猜想,由于缺少更复杂的gzip头,可能会有更多的简化

gzip在现代网络中的并行实现 多处理器、多核机器


答案就在你的问题里。每个线程都有自己的
deflate
实例来生成原始deflate数据(请参见
deflateInit2()
),它压缩提供给它的数据块,以
Z_SYNC\u FLUSH
而不是
Z_FINISH
结束。除了最后一块数据,它以
Z_FINISH
结尾。无论哪种方式,这都会在字节边界上结束每个压缩数据流。确保从
deflate()
中获取所有生成的数据。然后可以连接所有压缩数据流。(按照正确的顺序!)在前面加上您自己生成的gzip头。这样做是微不足道的(参见)。如果您不需要标头中包含任何附加信息(例如文件名、修改日期),则它可以是一个恒定的10字节序列。gzip头并不复杂

您还可以计算同一线程或不同线程中每个未压缩块的CRC-32,并使用
crc32\u combine()
组合这些CRC-32。gzip预告片需要这个

在写入所有压缩流之后,以压缩流结束,压缩流以
Z_FINISH
结束,您将附加gzip尾部。所有这些都是四字节CRC-32和总未压缩长度的低位四字节,两者都是小端顺序。总共八个字节

在每个线程中,您可以在处理每个区块时使用
deflateEnd()
,或者如果要为更多区块重用线程,请使用
deflateReset()
。我在pigz中发现,在处理多个块时,让线程保持打开状态,并在线程中打开
deflate
实例更有效。只需确保在关闭线程之前,对线程处理的最后一个块使用
deflateEnd()
。是,可以忽略
deflateEnd()
中的错误。只需确保已运行
deflate()
,直到
avail\u out
不为零即可获取所有压缩数据

执行此操作时,每个线程压缩其块而不引用任何其他未压缩的数据,这样的引用通常会在串行执行时改进压缩。如果希望更高级,可以向每个线程提供要压缩的未压缩数据块,以及前一个数据块的最后32K,以提供压缩器的历史记录。您可以使用
deflateSetDictionary()
执行此操作

更高级的是,有时可以使用
Z_PARTIAL_FLUSH
,直到达到字节边界,从而减少在压缩流之间插入的字节数。有关详细信息,请参见pigz

更高级但更慢的是,您可以在位级别而不是字节级别附加压缩流。这需要将压缩流的每个字节移位两次,以构建新的移位流。每八个之前的压缩流中至少有七个。这消除了压缩流之间插入的所有额外比特

zlib流可以用完全相同的方式生成,对校验和使用
adler32\u combine()


你关于zlib的问题意味着困惑。zip格式不使用zlib标头和尾部,其中嵌入原始放气流。您也可以对这些原始放气流使用上述方法。

Neat。现在,由于我已经编写了我自己的基于pthreads的代码来使用标准的zlib函数,我想知道您是否可以告诉我使用deflateInit2时需要使用哪些选项,或者该功能是否确实需要重写的zlib,即我需要使用pigz来实现这一点?你知道吗?(等一下,正在阅读源代码中的文档…)不,我不知道