高效地将多个 zlib 压缩数据流连接成一个流

DSn*_*net 7 python zlib

如果我有几个带有压缩 zlib 数据的二进制字符串,有没有办法有效地将它们组合成一个压缩字符串而不解压缩所有内容?

我现在必须做的示例:

c1 = zlib.compress("The quick brown fox jumped over the lazy dog. ")
c2 = zlib.compress("We ride at dawn! ")
c = zlib.compress(zlib.decompress(c1)+zlib.decompress(c2)) # Warning: Inefficient!

d1 = zlib.decompress(c1)
d2 = zlib.decompress(c2)
d = zlib.decompress(c)

assert d1+d2 == d # This will pass!
Run Code Online (Sandbox Code Playgroud)

我想要的例子:

c1 = zlib.compress("The quick brown fox jumped over the lazy dog. ")
c2 = zlib.compress("We ride at dawn! ")
c = magic_zlib_add(c1+c2) # Magical method of combining compressed streams

d1 = zlib.decompress(c1)
d2 = zlib.decompress(c2)
d = zlib.decompress(c)

assert d1+d2 == d # This should pass!
Run Code Online (Sandbox Code Playgroud)

我对 zlib 和 DEFLATE 算法不太了解,所以从理论的角度来看,这可能是完全不可能的。另外,我必须使用 use zlib;所以我不能包装 zlib 并提出我自己的协议来透明地处理连接流。

注意:如果解决方案在 Python 中不是微不足道的,我并不介意。我愿意编写一些 C 代码并在 Python 中使用 ctypes。

Ray*_*ger 7

由于您不介意冒险使用 C,您可以从查看gzjoin的代码开始

请注意,gzjoin代码必须解压缩才能找到合并时必须更改的部分,但不必重新压缩。这还不错,因为解压通常比压缩快。

  • @MarkAdler 谢谢,您为我们指明了正确的方向。我正在与 meawoppl 一起使用并行化的 PNG 压缩器。我们无法使用您建议的方法连接两个流,但我们能够使其以这种方式工作:对于第一个流,使用 Z_SYNC_FLUSH 调用 deflate。对于每个后续流,使用 Z_SYNC_FLUSH 调用 deflate,剥离 *first* 两个字节,并进行连接,同时收集 adler32 值和未压缩长度。然后对于最后一个流,用 Z_FINISH 放气,去除 4 字节校验和,并用所有校验和的 adler32_combine() 替换它。 (4认同)
  • 您可以使用“Z_SYNC_FLUSH”(或“Z_FULL_FLUSH”——在这种情况下无关紧要)完成紧缩,确保之后获得所有压缩数据(“strm.avail_out != 0”),然后跟随一个`Z_FINISH`。然后,您可以剥离流的最后两个字节,并直接将另一个 deflate 流连接到该流。 (3认同)
  • 具体回答这个问题,你不能像 gzjoin 那样在不解压缩第一个流的情况下组合两个 deflate 流。虽然如果您可以控制创建第一个 deflate 流,它可以专门准备附加到它而不解压缩。 (2认同)
  • 要找到内心的平静,请接受自己的本来面目,并接受他人的本来面目。 (2认同)

Mar*_*ler 5

除了需要解压第一个 deflate 流的 gzjoin 之外,您还可以查看gzlog.hgzlog.c,它们可以有效地将短字符串附加到 gzip 文件中,而无需每次都解压 deflate 流。(它可以很容易地修改为对 zlib 包装的 deflate 数据而不是 gzip 包装的 deflate 数据进行操作。)如果您可以控制第一个 deflate 流的创建,则可以使用这种方法。如果您不是创建第一个 deflate 流,那么您将不得不使用需要解压缩的 gzjoin 方法。

没有一种方法需要重新压缩。

  • 您可以通过仅解码第一个流来组合两个 deflate 流。然而,gzip 流并不总是在字节的末尾结束,因此 gzjoin.c 也会解码最后一个,以确保它知道 deflate 数据真正结束的位置以正确定位 crc 和长度。 (2认同)