8.2 gzip:读写GNU zip文件
gzip模块为GNU zip文件提供了一个类似文件的接口,他使用zlib来压缩和解压缩数据。
8.2.1 写压缩文件
模块级函数open()创建类似文件的GzipFile类的一个实例。它提供了读写字节的一般方法。
import gzip
import io
import os
outfilename = 'example.txt.gz'
with gzip.open(outfilename,'wb') as output:
with io.TextIOWrapper(output,encoding='utf-8') as enc:
enc.write('Contents of the example file go here.\n')
print(outfilename,'contains',os.stat(outfilename).st_size,
'bytes')
os.system('file -b - -mime {}'.format(outfilename))
为了把数据写至一个压缩文件,需要用模式’wb’打开文件。这个例子用io模块的一个TextIOWrapper来包装GzipFile,将Unicode文本编码为适合压缩的字节。
运行结果:
example.txt.gz contains 76 bytes
通过传入一个压缩级别(compresslevel)参数,可以使用不同的压缩量。合法值为0~9(包括0和9)。值越小便会得到越快的处理,得到的压缩也越少。较大的值会得到较慢的处理,但压缩更多(知道某个上限)。
import gzip
import io
import os
import hashlib
def get_hash(data):
return hashlib.md5(data).hexdigest()
data = open('lorem.txt','r').read() * 1024
cksum = get_hash(data.encode('utf-8'))
print('Level Size Checksum')
print('----- ---- --------')
print('data {:>10} {}'.format(len(data),cksum))
for i in range(0,10):
filename = 'compress=level-{}.gz'.format(i)
with gzip.open(filename,'wb',compresslevel=i) as output:
with io.TextIOWrapper(output,encoding='utf-8') as enc:
enc.write(data)
size = os.stat(filename).st_size
cksum = get_hash(open(filename,'rb').read())
print('{:>5d} {:>10d} {}'.format(i,size,cksum))
输出中,中间一列数字显示了压缩输入所生成文件的大小(字节数)。对于这个输入数据,压缩值更高并不一定能减少存储空间。根据输入数据的不同,结果会有变化。
运行结果:
GzipFile实例还包括一个writelines()方法,可以用来写字符串序列。
import gzip
import io
import itertools
import os
with gzip.open('example_lines.txt.gz','wb') as output:
with io.TextIOWrapper(output,encoding='utf-8') as enc:
enc.writelines(
itertools.repeat('The same line,over and over.\n',10))
os.system('gzcat example_lines.txt.gz')
与常规文件一样,输入行要包含一个换行符。
运行结果: