使用 zlib 重新压缩解压后的字符串

Re-compress a decompressed string with zlib

我有一个编码字符串,我在不知道它最初是如何编码的情况下设法解码的。这就是我设法解码的方式:

original_str = "LONG_SNIP" # Is clearly a base64 string
decoded_str = base64.b64decode(original_str) # Becomes unreadable mess
decompressed_str = zlib.decompress(decoded_str, -15) # Plain text, success

我想指出 zlib 参数“-15”是强制性的(-8 和 -15 之间的任何参数都有效)

但是,如果我想将纯文本字符串编码成完全相同的格式,以便上面的代码也能成功解码该格式,我 运行 就会遇到问题。

我查看了 zlib 文档并尝试了 zlib.compress,还创建了一个 compressobj 并尝试用它进行压缩,但没有成功。

这个'-15'值似乎不能输入任何函数来反转我原来做的解压。

这也是我尝试过的方法,但我得到的是空白输出:

compress = zlib.compressobj( 1, zlib.DEFLATED, -15, zlib.DEF_MEM_LEVEL, 0 ) 
deflated = compress.compress(string_to_compress)
encoded = base64.b64encode(deflated)
print(encoded)

问题:

整数参数是什么意思,为什么 -8 和 -15 之间的所有值都给出相同的精确输出?

更重要的是,我该如何逆转减压?

非常感谢回答,谢谢!

zlib.decompress() 的第二个参数是 wbits 参数。来自 documentation:

The wbits parameter controls the size of the history buffer (or “window size”), and what header and trailer format is expected. It is similar to the parameter for compressobj(), but accepts more ranges of values:

  • [...]
  • −8 to −15: Uses the absolute value of wbits as the window size logarithm. The input must be a raw stream with no header or trailer.
  • [...]

When decompressing a stream, the window size must not be smaller than the size originally used to compress the stream; using a too-small value may result in an error exception.

负值仅表示数据流中没有头部或尾部。

因此,如果 -8 和 -15 之间的任何值都有效,则压缩的 window 大小从一开始就非常小。更大的 window 大小需要更多的内存用于更大的历史缓冲区,但可以使解压缩速度更快。唯一的要求是它应该等于或大于用于压缩数据的数据块,否则将无法再找到对压缩流中使用的先前数据块的引用(我想,我确定 Mark Adler如果我错了,会纠正我的。

zlib manual 似乎暗示 wbits=8 实际上会自动替换为 wbits=9,并且可能 -8.

也会发生同样的情况

这转换为 zlib.compresobj() wbits 值介于 -9 和 -15 之间;再次来自文档:

  • −9 to −15: Uses the absolute value of wbits as the window size logarithm, while producing a raw output stream with no header or trailing checksum.

用最小的 window 大小压缩应该足够了:

compressor = zlib.compressobj(-1, zlib.DEFLATED, -9)
compressed = compressor.compress(data_to_compress) + compressor.flush()

演示:

>>> import zlib
>>> compressor = zlib.compressobj(-1, zlib.DEFLATED, -9)
>>> compressor.compress('foo bar baz') + compressor.flush()
'K\xcb\xcfWHJ,\x02\xe2*\x00'
>>> zlib.decompress(_, -8)
'foo bar baz'