如何从zlib压缩字符串中移除头部?

1 投票
1 回答
3683 浏览
提问于 2025-04-18 09:24

我正在使用 zlib 来压缩字符串,并且使用了一个强度为 9字典,这是我的脚本:

import zlib

__doc__ = """

rly this small py em ell thon... !? ha he hahaha hehehe h4ck3r wassup how ar u let's go lets go common c'mon...!!! ad

"""

class Compressor(object):
    def __init__(self, seed):
        c = zlib.compressobj(9)
        d_seed = c.compress(seed)
        d_seed += c.flush(zlib.Z_SYNC_FLUSH)
        self.c_context = c.copy()

        d = zlib.decompressobj()
        d.decompress(d_seed)
        while d.unconsumed_tail:
            d.decompress(d.unconsumed_tail)
        self.d_context = d.copy()

    def compress(self, text):
        c = self.c_context.copy()
        t = c.compress(text)
        t2 = c.flush(zlib.Z_FINISH)
        return t + t2

    def decompress(self, ctext):
        d = self.d_context.copy()
        t = d.decompress(ctext)
        while d.unconsumed_tail:
            t += d.decompress(d.unconsumed_tail)
        return t

c = Compressor(__doc__)

compressed_string = c.compress(string)

print compressed_string

string = "I installed python, and it's very nice and easy to use!"
compressed = c.compress(string)

print c.decompress(compressed)

我的问题是:从得到的 compressed_string 中,怎么去掉多余的部分,比如头部和最后的 4 个 ADLER 字节,这些在解压时会被附加上?如果我的定义有错,请纠正我。

比如说 12h3d78e23gdh278qs98qwjsj89qs1234 (其中 12 是理论上的 2 字节头部,1234 是理论上的 ADLER 部分在字符串的末尾),这段字符串应该变成 h3d78e23gdh278qs98qwjsj89qs,然后在 zlib 解压时会用类似的方式重建。

to_decompress = '12',compressed,'1234' 
c.decompress(to_decompress)

1 个回答

1

你已经有效地去掉了头部信息,因为它就在d_seed的前两个字节里。你不需要也不应该去掉Adler-32校验,因为如果你正确地重建压缩流,Adler-32会提供完整性检查。

你只需要把d_seed放在传输数据的前面,然后正常解压缩结果就可以了。

如果你使用的是Python 3.3或更高版本,做这件事的更好方法是用zlib来帮你处理字典。zlib.compressobj()zlib.decompressobj()的最后一个参数可以是字典。这样你还可以得到提供的字典的完整性检查,帮助确认在解压缩时使用的字典和压缩时的一样。这样处理后的流就是一个标准的zlib流,使用了字典,更加便于移植和识别。

如果你真的想节省六个字节(不推荐,因为这样会失去完整性检查),或者其实只想节省四个字节,因为你已经去掉了头部信息,那么可以在zlib.*compressobj()中把wbits参数设置为-15。这样会去掉zlib的头部和尾部。(这也需要3.3版本。)

撰写回答