这里的关键是这是一个巨大的文件。我的目标是避免立即将整个文件读入内存,并避免解析循环中的每一行以获得我需要的行(因为它需要永远。文件长度为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
过滤器不会实现我的目标需要。我必须按行搜索,而不是按数据搜索。
答案 0 :(得分:3)
一种简单的方法是利用有效gzip流的串联是一个gzip流这一事实。然后在压缩时,您可以将行块压缩为单独的gzip流,并记录文件中gzip流的起始位置,以及该流中压缩的第一行的行号。然后你可以跳到那个位置并从那里开始解压缩。如果你的块大约是兆字节(大约50,000行),那么压缩率应该相对较小。然后平均而言,您需要解压缩25,000行才能到达任何给定的行,而不是750万行。
如果您无法控制gzip文件的创建,并且无法根据需要重新创建它,那么您可以使用zran.c中使用的方法索引现有的gzip文件。您可以指定您希望接入点的接近程度,并且它将构建一个索引,允许从每个点开始访问。您还需要为行开始构建索引(就像对未压缩文件一样),将具有字节偏移的索引与未压缩数据相关联。
答案 1 :(得分:1)
您将无法在gzip文件中精确定位随机访问的指定行,但您可以在压缩文件中使用索引,然后使用1000行或其他内容精确定位块。 indexed-gzip可能是一种选择。
然而,查看数据让我想知道你是否不能手动进行压缩。如果将压缩设置为固定长度,则可以计算文件中每行开始的位置,然后从该位置读取。似乎每一行只能用两个数字表示。或者我不理解格式?