python - gz 文件解压缩过程的不同行为

标签 python linux zip compression gzip

我有几个解压缩似乎无法正常工作的 gz 文件。我选择了其中一个,该文件位于本地文件夹中,并且来自外部来源。我不知道压缩过程。

我创建了一个 python 脚本来说明情况。为了获得用于测试的引用文件,我解压缩了 gz 文件并再次压缩(在 Ubuntu 上使用 gzip)以在我的计算机中生成相同的 gz 文件。这两个文件呈现不同的行为:

    import gzip
    import zlib
    import hashlib

    def md5(content):
        m = hashlib.md5()
        m.update(content)
        return m.hexdigest()

    def decompress_gzip_size(file_name):
        with gzip.open(file_name, 'rb') as f_out:
            f_content = f_out.read()
            print(len(f_content), file_name)
            print (md5(f_content), file_name)

    def decompress_open_gzip_size(file_name):
        with open(file_name, 'rb') as f_out:
            f_content = f_out.read()
            unzip_content = gzip.decompress(f_content)
            print(len(unzip_content), file_name)
            print (md5(unzip_content), file_name)

    def decompress_zlib_size(file_name):
        with open(file_name, 'rb') as f_out:
            f_content = f_out.read()
            unzip_content = zlib.decompress(f_content, 32)
            print(len(unzip_content), file_name)
            print (md5(unzip_content), file_name)

    def decompress_zlib_obj(file_name):
        decompress_obj = zlib.decompressobj(32)
        with open(file_name, 'rb') as f_out:
            f_content = f_out.read()
            unzip_content = decompress_obj.decompress(f_content)
            print(len(unzip_content), file_name)
            print(len(decompress_obj.unused_data), 'Unused data')
            print (md5(unzip_content), file_name)

    external_file = 'external_source_compress.gz'
    my_file = 'my-compress-file.gz'

    print("decompress_gzip_size")
    decompress_gzip_size(my_file)
    decompress_gzip_size(external_file)
    print("*" * 60)

    print("decompress_open_gzip_size")
    decompress_open_gzip_size(my_file)
    decompress_open_gzip_size(external_file)
    print("*" * 60)

    print("decompress_zlib_size")
    decompress_zlib_size(my_file)
    decompress_zlib_size(external_file)
    print("*" * 60)

    print("decompress_zlib_obj")
    decompress_zlib_obj(my_file)
    decompress_zlib_obj(external_file)
    print("*" * 60)

执行输出为:

    decompress_gzip_size
    167019534 my-compress-file.gz
    a4dd17dd28b89f0b2c300b607cd1a8ba my-compress-file.gz
    167019534 external_source_compress.gz
    a4dd17dd28b89f0b2c300b607cd1a8ba external_source_compress.gz
    ************************************************************
    decompress_open_gzip_size
    167019534 my-compress-file.gz
    a4dd17dd28b89f0b2c300b607cd1a8ba my-compress-file.gz
    167019534 external_source_compress.gz
    a4dd17dd28b89f0b2c300b607cd1a8ba external_source_compress.gz
    ************************************************************
    decompress_zlib_size
    167019534 my-compress-file.gz
    a4dd17dd28b89f0b2c300b607cd1a8ba my-compress-file.gz
    33408639 external_source_compress.gz
    4f51ccc64a7baab5ee5e2ce31e816409 external_source_compress.gz
    ### SIZES AND MD5 DO NOT MATCH ###
    ************************************************************
    decompress_zlib_obj
    167019534 my-compress-file.gz
    0 Unused data
    a4dd17dd28b89f0b2c300b607cd1a8ba my-compress-file.gz
    33408639 external_source_compress.gz
    46765202 Unused data
    4f51ccc64a7baab5ee5e2ce31e816409 external_source_compress.gz
    ### THERE IS SOME UNUSED DATA IN THE ORIGINAL FILE ###
    ************************************************************

注意:如果窗口大小参数不是 32,zlib 解压缩将失败。

在没有设置窗口大小的情况下发生了这种情况:

    Traceback (most recent call last):
      File "decompress_python.py", line 53, in <module>
        decompress_zlib_size(my_file)
      File "decompress_python.py", line 26, in decompress_zlib_size
        unzip_content = zlib.decompress(f_content)
    zlib.error: Error -3 while decompressing data: incorrect header check

可以看出。如果没有 32 的窗口大小,脚本会崩溃,但是如果窗口大小为 32,它会完成,但是读取的字节数只是实际数据量的一部分。

文件内部只有一个元素:

    gzip -l external_source_compress.gz
             compressed        uncompressed  ratio uncompressed_name
               58609586            33410520 -75.4% external_source_compress

谁能帮我理解这里发生了什么?我真的迷路了。提前致谢。

最佳答案

Florian 的回答几乎可以肯定是发生了什么,即您只是部分解压的 gzip 文件必须有多个成员。要解压下一个成员,您可以简单地从decompressobj 对象中获取unused_data 并开始另一个解压。重复直到使用完所有输入。

This answer显示了在 python 中处理具有多个成员的 gzip 文件的示例。

听起来您应该为 wbits 参数使用的是 31,而不是 32。31 需要 gzip 包装器而不是 zlib 包装器。不指定 wbits 会导致解压缩器需要一个 zlib 包装器,这就是它不能在您的 gzip 流上工作的原因。

关于python - gz 文件解压缩过程的不同行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52624756/

相关文章:

python - 字节码优化

java - 更改 python 脚本中的 $JAVA_HOME

linux - 如何在列中格式化控制台输出

ASP.NET - response.outputstream.write 要么写入 16k,然后全为 0,要么每 64k 写入除 insetrs 之外的所有字符

java - 将 DeflaterInputStream 功能移植到 .net

Python 不读取整个文本文件

linux - 在linux中预留物理地址空间

linux - Linux 下如何知道内存去了哪里

Java - 打包文件 (zip) 更改最后修改日期

python - 按 X 列对数据框进行分组