首页 > Python基础教程 >
-
Python3标准库:zlib GNUzlib压缩
1. zlib GNUzlib压缩
zlib模块为GNU项目zlib压缩库中的很多函数提供了底层接口。
1.1 处理内存中的数据
使用zlib最简单的方法要求把所有将要压缩或解压缩的数据存放在内存中。
- import zlib
- import binascii
- original_data = b'This is the original text.'
- print('Original :', len(original_data), original_data)
- compressed = zlib.compress(original_data)
- print('Compressed :', len(compressed),
- binascii.hexlify(compressed))
- decompressed = zlib.decompress(compressed)
- print('Decompressed :', len(decompressed), decompressed)
compress()和decompress()函数都取一个字节序列参数,并且返回一个字节序列。
从前面的例子可以看到,少量数据的压缩版本可能比未压缩的版本还要大。具体的结果取决于输入数据,不过观察小数据集的压缩开销很有意思。
- import zlib
- original_data = b'This is the original text.'
- template = '{:>15} {:>15}'
- print(template.format('len(data)', 'len(compressed)'))
- print(template.format('-' * 15, '-' * 15))
- for i in range(5):
- data = original_data * i
- compressed = zlib.compress(data)
- highlight = '*' if len(data) < len(compressed) else ''
- print(template.format(len(data), len(compressed)), highlight)
输出中的*突出显示了哪些行的压缩数据比未压缩版本占用的内存更多。
zlib支持不同的压缩级别,允许在计算成本和空间缩减量之间有所平衡。默认压缩级别zlib.Z_DEFAULT_COMPRESSION为-1,这对应一个硬编码值,表示性能和压缩结果之间的一个折中。当前这对应级别6。
- import zlib
- input_data = b'Some repeated text.\n' * 1024
- template = '{:>5} {:>5}'
- print(template.format('Level', 'Size'))
- print(template.format('-----', '----'))
- for i in range(0, 10):
- data = zlib.compress(input_data, i)
- print(template.format(i, len(data)))
压缩级别为0意味着根本没有压缩。级别9要求的计算最多,同时会生成最小的输出。如下面的例子,对于一个给定的输入,可以多个压缩级别得到的空间缩减量是一样的。
1.2 增量压缩与解压缩
这种内存中的压缩方法有一些缺点,主要是系统需要有足够的内存,可以在内存中同时驻留未压缩和压缩版本,因此这种方法对于真实世界的用例并不实用。另一种方法是使用Compress和Decompress对象以增量方式处理数据,这样就不需要将整个数据集都放在内存中。
- import zlibimport binascii
- compressor = zlib.compressobj(1)
- with open('lorem.txt','rb') as input:
- while True:
- block = input.read(64)
- if not block:
- break
- compressed = compressor.compress(block)
- if compressed:
- print('Compressed: {}'.format(
- binascii.hexlify(compressed)))
- else:
- print('buffering...')
- remaining = compressor.flush()
- print('Flushed: {}'.format(binascii.hexlify(remaining)))
这个例子从一个纯文本文件读取小数据块,并把这个数据集传至compress()。压缩器维护压缩数据的一个内存缓冲区。由于压缩算法依赖于校验和以及最小块大小,所以压缩器每次接收更多输入时可能并没有准备好返回数据。如果它没有准备好一个完整的压缩块,那便会返回一个空字节串。当所有
1.3 混合内容流
在压缩和未压缩数据混合在一起的情况下,还可以使用decompressobj()返回的Decompress类。
- import zlib
- lorem = open('lorem.txt','rb').read()
- compressed = zlib.compress(lorem)
- combined = compressed +lorem
- decompressor = zlib.decompressobj()
- decompressed = decompressor.decompress(combined)
- decompressed_matches = decompressed ==