如何在Python中对字节数组进行gzip压缩?

12

我有一个字节数组中的二进制数据,我想先使用gzip压缩,然后通过请求发送。我找到了如何压缩文件,但没有找到如何压缩字节数组的方法。那么,我该如何通过Python对字节数组进行gzip压缩呢?


丑陋的方法:将其保存在文件中:P。但也许这会有所帮助:https://dev59.com/ZWoy5IYBdhLWcg3wguSS - Vincent Beltman
4个回答

17

看一下Python的zlib模块。

Python 3: zlib模块

一个简短的示例:

import zlib
compressed_data = zlib.compress(my_bytearray)

你可以通过以下方法再次解压数据:

decompressed_byte_data = zlib.decompress(compressed_data)

Python 2:zlib 模块

一个简短的示例:

import zlib
compressed_data = zlib.compress(my_string)

您可以通过以下方式再次解压数据:

decompressed_string = zlib.decompress(compressed_data)

正如你所看到的,Python 3 使用字节数组(bytearrays),而 Python 2 使用字符串(strings)。


2
对我来说,它需要一个字符串,而不是字节数组.. compressedData = zlib.compress(mystring) - mgear
3
那是因为你正在使用 Python 2,它需要一个输入字符串 - 在 Python 3 中,该函数需要一个字节数组...我已经在我的答案中添加了这个信息。 - mozzbozz
请注意,此方法与gzip命令行实用程序不兼容,因为gzip包括头和校验和,而此机制仅压缩内容。如果您想生成一个完整的gzip兼容二进制字符串,包括头等,请使用gzip.GzipFile和StringIO。 - Mathieu Rey

1

如果bytearray不太大,可以在内存中存储多次,并且已知为b,您只需执行以下操作:

b_gz = str(b).encode('zlib')

如果您需要先进行解码,请查看bytearray的decode()方法。

1
我不确定这是否正确?如果你在一个bytearray上调用str(),你会得到类似于"bytearray(b'test')"的东西 - 但他想要压缩bytearray而不是描述bytearray的字符串(我认为这在某些特殊情况下可能会导致数据丢失?)。 - mozzbozz
1
我刚刚发现这段代码只能在Python 2中运行。在Python 3中,该领域已经发生了一些变化。 - Klaus D.
2
好的,这正是我想到的(我主要使用Python 3)。你可以在你的帖子中加上一条注释,提醒那些没有阅读“第一次尝试”评论的人。 - mozzbozz

1
Python标准库中的zlib模块应该能够满足您的需求:
>>> import zlib
>>> a = b'abcdefghijklmn' * 10
>>> ca = zlib.compress(a)
>>> len(a)
140
>>> len(ca)
25
>>> b = zlib.decompress(ca)
>>> b == a
True
>>> b
b'abcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmn'

这是在Python3.4下的输出,但在Python2.7下也可以正常工作 -

1
import zlib 
import binascii


def compress_packet(packet):
    return zlib.compress(buffer(packet),1)

def decompress_packet(compressed_packet):
    return zlib.decompress(compressed_packet)

def demo_zlib() :

    packet1 = bytearray()
    packet1.append(0x41)
    packet1.append(0x42)
    packet1.append(0x43)
    packet1.append(0x44)

    print "before compression: packet:{0}".format(binascii.hexlify(packet1))
    cpacket1 = compress_packet(packet1)
    print "after compression: packet:{0}".format(binascii.hexlify(cpacket1))

    print "before decompression: packet:{0}".format(binascii.hexlify(cpacket1))
    dpacket1 = decompress_packet(buffer(cpacket1))
    print "after decompression: packet:{0}".format(binascii.hexlify(dpacket1))


def main() :
    demo_zlib() 

if __name__ == '__main__' :
    main() 

这样就可以了。zlib需要访问字节数组内容,使用buffer()即可。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接