gz 文件解压缩过程的不同行为
Different behaviours for gz files decompress process
我有几个解压缩似乎无法正常工作的 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 ###
************************************************************
注意:如果 window 大小参数不是 32,则 zlib 解压失败。
在不设置 window 尺寸的情况下发生了这种情况:
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 windows-size,脚本会崩溃,但是如果有 window-size 32,它会完成,但是读取的字节数只是实际数据量的一部分。
文件里面只有一个元素:
gzip -l external_source_compress.gz
compressed uncompressed ratio uncompressed_name
58609586 33410520 -75.4% external_source_compress
任何人都可以帮助我了解这里发生的事情吗?我真的迷路了。提前致谢。
gzip 流可以包含多个独立压缩的项目,然后将它们简单地连接起来。期望 gzip 样式的解压缩器透明地读取所有独立压缩的部分,生成单个输出流(基本上忽略内部流结束指示符)。
zlib.compressobj
的文档没有说,但它会在第一个 zlib 检测到的内部流结束条件处停止。然后可以独立处理剩余的数据。在某些应用程序中(但不是您的应用程序),它甚至可能不是 zlib 压缩数据。
Florian 的回答几乎可以肯定是怎么回事,就是你只是部分解压的 gzip 文件必须有多个成员。要解压下一个成员,您只需从 decompressobj
对象中获取 unused_data
并开始另一个解压。重复直到使用所有输入。
This answer 在 python.
中显示了处理具有多个成员的 gzip 文件的示例
听起来您应该为 wbits
参数使用的是 31,而不是 32。31 需要 gzip 包装器而不是 zlib 包装器。不指定 wbits
会导致解压缩器需要一个 zlib 包装器,这就是它不能在您的 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 ###
************************************************************
注意:如果 window 大小参数不是 32,则 zlib 解压失败。
在不设置 window 尺寸的情况下发生了这种情况:
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 windows-size,脚本会崩溃,但是如果有 window-size 32,它会完成,但是读取的字节数只是实际数据量的一部分。
文件里面只有一个元素:
gzip -l external_source_compress.gz
compressed uncompressed ratio uncompressed_name
58609586 33410520 -75.4% external_source_compress
任何人都可以帮助我了解这里发生的事情吗?我真的迷路了。提前致谢。
gzip 流可以包含多个独立压缩的项目,然后将它们简单地连接起来。期望 gzip 样式的解压缩器透明地读取所有独立压缩的部分,生成单个输出流(基本上忽略内部流结束指示符)。
zlib.compressobj
的文档没有说,但它会在第一个 zlib 检测到的内部流结束条件处停止。然后可以独立处理剩余的数据。在某些应用程序中(但不是您的应用程序),它甚至可能不是 zlib 压缩数据。
Florian 的回答几乎可以肯定是怎么回事,就是你只是部分解压的 gzip 文件必须有多个成员。要解压下一个成员,您只需从 decompressobj
对象中获取 unused_data
并开始另一个解压。重复直到使用所有输入。
This answer 在 python.
中显示了处理具有多个成员的 gzip 文件的示例听起来您应该为 wbits
参数使用的是 31,而不是 32。31 需要 gzip 包装器而不是 zlib 包装器。不指定 wbits
会导致解压缩器需要一个 zlib 包装器,这就是它不能在您的 gzip 流上工作的原因。