【问题标题】:How to inflate a partial zlib file如何膨胀部分 zlib 文件
【发布时间】:2013-12-16 20:35:46
【问题描述】:

我有一个用 zlib 的 deflate() 函数压缩的文件的前连续 2/3。最后 1/3 在传输中丢失。原始未压缩文件为 600KB。

Deflate 被发送器多次调用,同时将原始文件切成 2KB 的块大小并传递 Z_NO_FLUSH,直到传递 Z_FINISH 时文件结束。生成的完整压缩文件已传输,但如所述部分丢失。

是否可以恢复部分原始文件?如果是的话,有什么建议吗?

我正在使用 ZLIB 的纯 C 实现和/或 ZLIB 的 Python 2.7 实现。

【问题讨论】:

    标签: python c zlib compression


    【解决方案1】:

    虽然我不懂python,但我设法让它工作:

    #!/usr/bin/python
    import sys
    import zlib
    f = open(sys.argv[1], "rb")
    g = open(sys.argv[2], "wb")
    z = zlib.decompressobj()
    while True:
        buf = z.unconsumed_tail
        if buf == "":
            buf = f.read(8192)
            if buf == "":
                break
        got = z.decompress(buf)
        if got == "":
            break
        g.write(got)
    

    这应该会从您的部分 zlib 文件中提取所有可用的内容。

    【讨论】:

    • 谢谢,是的,使用 decompressobj() 有效。我只是在使用 zlib.decompress() 并且它给出了一个错误。使用 dc_obj = zlib.decompressobj() 和 decomp_data_str = dc_obj.decompress(orig_data_str) 解决了这个问题。
    【解决方案2】:

    更新:作为@Mark Adler pointed out;部分内容可以使用zlib.decompressobj解压:

    >>> decompressor = zlib.decompressobj()
    >>> decompressor.decompress(part)
    "let's compress some t"
    

    part 定义如下。

    --- 旧评论如下:

    默认情况下,zlib 不处理 Python 中的部分内容。

    这行得通:

    >>> compressed = "let's compress some text".encode('zip')
    >>> compressed
    'x\x9c\xcbI-Q/VH\xce\xcf-(J-.V(\xce\xcfMU(I\xad(\x01\x00pX\t%'
    >>> compressed.decode('zip')
    "let's compress some text"
    

    如果我们截断它就行不通了:

    >>> part = compressed[:3*len(compressed)/4]
    >>> part.decode('zip')
    Traceback (most recent call last):
      File "<input>", line 1, in <module>
      File ".../lib/python2.7/encodings/zlib_codec.py", lin
    e 43, in zlib_decode
        output = zlib.decompress(input)
    error: Error -5 while decompressing data: incomplete or truncated stream
    

    如果我们明确地使用zlib,也是一样的:

    >>> import zlib
    >>> zlib.decompress(compressed)
    "let's compress some text"
    >>> zlib.decompress(part)
    Traceback (most recent call last):
      File "<input>", line 1, in <module>
    error: Error -5 while decompressing data: incomplete or truncated stream
    

    【讨论】:

      【解决方案3】:

      以下似乎在理论上是可行的,但需要修改低级 zlib 例程才能工作。在http://www.zlib.net/zlib_how.html 中我们找到了一个示例程序zpipe.c,并在其逐行描述中:

      CHUNK 只是用于向 zlib 例程提供数据和从 zlib 例程中提取数据的缓冲区大小。更大的缓冲区大小会更有效,尤其是对于 inflate()。如果内存可用,则应使用大小约为 128K 或 256K 字节的缓冲区。

      #define CHUNK 16384
      ...
      

      这是我的建议:您将缓冲区设置得非常小——如果支持,甚至可以设置为单个字节。这样,您将尽可能地解压缩到不可避免的Z_BUF_ERROR。那时,通常会丢弃收集到的数据(寻找过早的 deflate_end 调用在你背后“清理”),但在你的情况下,你可以简单地流式传输到文件并在发现无法继续时关闭它.

      如果错误的“最终”符号被解码,则输出的最后几个字节可能包含抖动,或者 zlib 可能会过早中止,而不是输出部分符号。但是您知道您的数据将是不完整的无论如何,所以这应该不是问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-10
        • 2014-07-25
        相关资源
        最近更新 更多