简体   繁体   English

如何读取没有标题或mimetype的Gzip字符串? 使用Python

[英]How to read a Gzip String with no header or mimetype? Using Python

I have a gzipped string, it is created an stored from another application. 我有一个压缩的字符串,它是从另一个应用程序存储的。 Now that I have the string (no mimetype or headers attached), I need to uncompress it. 现在,我已经有了字符串(没有附加mimetype或标头),我需要解压缩它。

Is there a way to do this in Python? 有没有办法在Python中做到这一点?

[EDIT] To test I literally copied then pasted the string into notepad and then renamed as .gz I've also tested by pasting the string itself into IDLE [编辑]为进行测试,我从字面上进行了复制,然后将字符串粘贴到记事本中,然后重命名为.gz我还通过将字符串本身粘贴到IDLE中进行了测试

Other examples I've seen assume a filetype and mimetype are available and all I have is a big string. 我见过的其他示例假定文件类型和mimetype可用,而我所拥有的只是一个大字符串。

Using zlib.decompress(mystring) gives error Error -3 while decompressing data: incorrect header check Error -3 while decompressing data: incorrect header check使用zlib.decompress(mystring)会产生Error -3 while decompressing data: incorrect header check

Confirming the comments by @reclosedev, and adding some more: 通过@reclosedev确认评论,并添加更多内容:

The bytes after the ] need to be base64-decoded. ]之后的字节需要进行base64解码。

In the result of that, there are 4 bytes constituting the length of the decompressed data as a 32-bit little-endian binary number. 结果,有4个字节构成了解压缩数据的长度,作为32位的little-endian二进制数。 The remainder is an RFC-1952-compliant gzip stream, recognisable by starting with 1F 8B 08 . 其余部分是符合RFC-1952的gzip流,可以从1F 8B 08开始识别。 The decompression results look like binary data, not strings of ASCII 1s and 0s. 解压缩结果看起来像二进制数据,而不是ASCII 1和0的字符串。

Code: 码:

lines = [
    # extracted from the linked csv file 
    "[133,120,696,286]MmEAAB+LCAAAAAAABADtvQdg [BIG snip] a0bokyYQAA",
    "[73,65,564,263]bkgAAB+LCAAAAAAABADtvQdgHE [BIG snip] kgAAA==",
    ]
import zlib, struct
for line in lines:
    print
    b64 = line.split(']')[1]
    raw = b64.decode('base64')
    print "unknown:", repr(raw[:4])
    print "unknown as 32-bit LE int:", struct.unpack("<I", raw[:4])[0]
    ungz = zlib.decompress(raw[4:], 31)
    print len(ungz), "bytes in decompressed data"
    print "first 100:", repr(ungz[:100])

Output: 输出:

unknown: '2a\x00\x00'
unknown as 32-bit LE int: 24882
24882 bytes in decompressed data
first 100: '\xff\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00
\x00\x00\x00'

unknown: 'nH\x00\x00'
unknown as 32-bit LE int: 18542
18542 bytes in decompressed data
first 100: '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\xff\xff\xff\xff
\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
\x00\x00\x00\x00\x07\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80
\x00\x00\x00'

Update in response to comment 更新以回应评论

To get the 1s and 0s I needed I just added this to the above 为了得到1和0,我需要将其添加到上面
cleaned = bin(int(binascii.hexlify(ungz), 16)) 清理= bin(int(binascii.hexlify(ungz),16))

"Just"? “只是”? You would need to strip off '0b' from the front, and then pad the front with as many leading zeroes as necessary to make the length a multiple of 8. Example, with a better method: 您需要从前面剥去'0b' ,然后在前面填充尽可能多的前导零,以使长度为8的倍数。例如,使用更好的方法:

>>> import binascii
>>> ungz = '\x01\x80'
>>> bin(int(binascii.hexlify(ungz), 16))
'0b110000000'
>>> ''.join('{0:08b}'.format(ord(x)) for x in ungz)
'0000000110000000'

Have you checked carefully to ensure that you really want '0000000110000000' and not '1000000000000001' ? 您是否已仔细检查以确保您确实要'0000000110000000'而不是'1000000000000001'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM