1

这里的关键是这是一个巨大的文件。我的目标是避免一次将整个文件读入内存,并避免解析循环中的每一行以到达我需要的行(因为它需要很长时间。该文件实际上有 1500 万行长)。

我目前正在做的是将文件打开为...

self._FH = gzip.open(filename, "rb")

...将指针直接移动到所需行的位置(使用许多恶作剧,但它有效)并在单独的行中读取。

类似于下面的行(尽管这些示例来自文件的开头,为了方便和信息起见)......

b'BAM\x01\x17\x18\x00\x00@HD\tVN:1.0\tSO:coordinate\n'
b'@SQ\tSN:1\tLN:248956422\n'
b'@SQ\tSN:10\tLN:133797422\n'
b'@SQ\tSN:11\tLN:135086622\n'
b'@SQ\tSN:12\tLN:133275309\n'
b'@SQ\tSN:13\tLN:114364328\n'
b'@SQ\tSN:14\tLN:107043718\n'
b'@SQ\tSN:15\tLN:101991189\n'
b'@SQ\tSN:16\tLN:90338345\n' 
b'@SQ\tSN:17\tLN:83257441\n'
b'@SQ\tSN:18\tLN:80373285\n'

有些人可能会注意到这是一个BAM文件,所以如果有更好的方法可以做到这一点,欢迎提出建议……尽管samtools过滤器无法满足我的需要。我必须按行搜索,而不是按数据搜索。

4

2 回答 2

4

一种简单的方法是利用有效 gzip 流的串联是 gzip 流这一事实。然后在压缩时,您可以将大块的行压缩成单独的 gzip 流,并记下 gzip 流在文件中的起始位置,以及该流中压缩的第一行的行号。然后你可以跳到那个位置并从那里开始解压缩。如果您的块大约为兆字节(大约 50,000 行),那么压缩率的降低应该相对较小。那么平均而言,您需要解压缩 25,000 行才能到达任何给定行,而不是 750 万行。

如果您无法控制 gzip 文件的创建,并且无法根据需要重新创建它,那么您可以使用zran.c中使用的方法索引现有 gzip 文件。你可以指定你希望你的访问点有多近,它会建立一个索引,允许从每个点开始访问。您还需要为您的行开头建立一个索引(就像您为未压缩文件所做的那样),以将具有字节偏移的那些与未压缩数据相关联。

于 2017-11-10T21:00:31.870 回答
2

您将无法在 gzip 文件中查明用于随机访问的特定行,但您可以使用压缩文件中的索引,然后查明包含 1000 行或其他内容的块。indexed-gzip可能是一种选择。

但是,查看数据让我想知道您是否不能仅手动进行压缩。如果您将压缩到固定长度,您可以计算文件中每一行的开始位置,然后从该位置读取。似乎每条线只能用两个数字表示。还是我看不懂格式?

于 2017-11-10T19:17:37.797 回答