如何对gzip压缩文件进行随机访问

3 投票
4 回答
2998 浏览
提问于 2025-04-18 01:56

根据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的分发包里。

撰写回答