逐行读取80GB .gz文件的内容而不解压缩它

use*_*734 2 c python compression tar

我有一个80GB的.gz文件(http://storage.googleapis.com/books/ngrams/books/googlebooks-eng-all-3gram-20120701-th.gz),其中包含一个更大的制表符分隔文件.有没有一种方法可以在不将80GB加载到内存或解压缩文件的情况下逐行重现该文件的内容?我需要该文件中的特定行(大约10000)但我没有80GB的RAM或超过1TB的存储空间来解压缩它.

小智 6

您可以使用zcat将未压缩的内容流式传输到所需的grep任何过滤器,而不会产生空间开销.例如

zcat bigfile.gz | grep PATTERN_I_NEED > much_smaller_sample
Run Code Online (Sandbox Code Playgroud)

此外,如果它只是grep你正在流式传输,你可以使用zgrep例如

zgrep PATTERN_I_NEED bigfile.gz > much_smaller_sample
Run Code Online (Sandbox Code Playgroud)

zgrep不支持grep某些系统100%的功能.


Mar*_*ers 5

解压缩以块的形式进行,您无需将所有解压缩的数据保存在内存中即可到达特定行。

可以将gzip模块csv模块结合起来,逐行处理文件:

import gzip
import csv

with gzip.open('googlebooks-eng-all-3gram-20120701-th.gz', 'rb') as fobj:
    reader = csv.reader(fobj, delimiter='\t')
    for row in reader:
        print row
Run Code Online (Sandbox Code Playgroud)

现在您可以扫描所需的行;只要您不尝试将所有行存储在列表对象中,而是单独处理它们,就根本不会使用太多内存。

快速演示:

>>> import gzip
>>> import csv
>>> fobj = gzip.open('/tmp/googlebooks-eng-all-3gram-20120701-th.gz', 'rb')
>>> reader = csv.reader(fobj, delimiter='\t')
>>> print next(reader)
["T'Hooft , _NOUN_", '1937', '1', '1']
Run Code Online (Sandbox Code Playgroud)

我在这里使用该next()函数一次仅从读取器获取一行,但其原理与在循环中使用读取器相同。

上面使用的内存很少;文件缓冲区和当前要解压缩的块以及列表中的 Python 字符串不超过几千字节row