python - gz文件解压过程的不同行为
问题描述
我有几个 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 文件必须有多个成员。要解压下一个成员,您可以简单地unused_data
从decompressobj
对象中获取并开始另一个解压。重复直到使用所有输入。
此答案显示了在 python 中处理具有多个成员的 gzip 文件的示例。
听起来您应该为wbits
参数使用的是 31,而不是 32。31 需要一个 gzip 包装器,而不是一个 zlib 包装器。未指定wbits
解压缩器会导致需要 zlib 包装器,这就是它不适用于您的 gzip 流的原因。
推荐阅读
- git - 创建新分支不会为 IntelliJ 中的所有模块创建分支
- reactjs - 如何路由到另一个组件并替换当前组件?
- python - Discord 机器人无法播放音乐
- c++ - 指定初始化程序中参数列表的大括号数
- typescript - 鸭子在 Typescript 中输入一个 Promise
- android - 自定义recyclerview项目android
- java - org.json 避免将空字段反序列化为 JSONObject.Null
- listview - JavaFX - 如何将附件/文件链接添加到每个 tableview 对象
- r - 如何将图例添加到matplot?
- google-cloud-firestore - 如何使用动态路径编写 Firestore 安全规则?