如何对gzip压缩文件进行随机访问
根据zlib.net上的这个常见问题解答,我们可以:
在压缩流中随机访问数据
我知道有一个模块叫做Bio.bgzf,属于Biopyton 1.60,这个模块:
支持读取和写入BGZF文件(阻塞GNU压缩格式),这是一种GZIP的变体,能够高效地进行随机访问,通常用于BAM文件格式和tabix中。它内部使用Python的zlib库,并提供了一个像Python的gzip库一样简单的接口。
但对于我的使用场景,我不想使用那种格式。基本上,我想要的是一种能模拟下面这段代码的东西:
import gzip
large_integer_new_line_start = 10**9
with gzip.open('large_file.gz','rt') as f:
f.seek(large_integer_new_line_start)
但是要利用zlib.net提供的高效随机访问能力,来处理压缩流。我该如何在Python中利用这种随机访问的功能呢?
4 个回答
-3
如果你只是想从某个随机位置访问文件,难道你不可以直接这样做吗:
from random import randint
with open(filename) as f:
f.seek(0, 2)
size = f.tell()
f.seek(randint(0, size), 2)
0
indexed_gzip这个程序可能正是你需要的。它的底层也使用了zran.c
这个文件。
0
你在找的是 dictzip.py
,它是 serpento 这个软件包的一部分。不过,你需要用 dictzip
来压缩文件,这是一种可以随机访问、向后兼容的 gzip
压缩变种。
7
我放弃了用Python对gzipped文件进行随机访问。于是,我使用命令行工具把gzipped文件转换成了块压缩的gzipped文件,这个工具叫做块压缩/解压缩工具。
zcat large_file.gz | bgzip > large_file.bgz
接着,我用BioPython来获取这个bgzipped文件中第100万行的虚拟偏移量。之后,我就能快速定位到这个虚拟偏移量了:
from Bio import bgzf
file='large_file.bgz'
handle = bgzf.BgzfReader(file)
for i in range(10**6):
handle.readline()
virtual_offset = handle.tell()
line1 = handle.readline()
handle.close()
handle = bgzf.BgzfReader(file)
handle.seek(virtual_offset)
line2 = handle.readline()
handle.close()
assert line1==line2
我还想提一下Mark Adler在SO上的回答,里面有关于examples/zran.c的内容,这些都在zlib的分发包里。