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

时间:2014-08-15 16:30:52

标签: python c compression tar

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

6 个答案:

答案 0 :(得分:6)

您可以使用zcat将未压缩的内容流式传输到grep或您想要的任何过滤器,而不会产生空间开销。 E.g。

zcat bigfile.gz | grep PATTERN_I_NEED > much_smaller_sample

此外,如果只是grep,您正在直播,您可以使用zgrep,例如

zgrep PATTERN_I_NEED bigfile.gz > much_smaller_sample

zgrep在某些系统上不支持grep的100%功能。

答案 1 :(得分:3)

解压缩发生在中,您不需要将所有解压缩的数据保存在内存中以到达特定的行。

您可以将gzip modulecsv module结合使用,然后逐行处理文件:

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

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

快速演示:

>>> 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']

我在这里使用next() function一次只能从阅读器中获取一行,但其原理与在循环中使用阅读器的原则相同。

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

答案 2 :(得分:0)

不幸的是,您需要从头开始解压缩。但是,您不需要立即将其全部读入内存。据我所知,python实现读入内存,但你可以运行gzip作为外部工具,并使用它的stdout作为你的csv阅读器的源。这样可以在单独的处理器中并行解压缩。

答案 3 :(得分:0)

如果您想使用python,请查看gzip。前提与迭代常规文本文件相同,即

import gzip
gz = gzip.GzipFile('/path/file.gz')
for i in gz:
    print(i)

答案 4 :(得分:-1)

答案 5 :(得分:-1)

这是我过去使用过的

  BUFF_SIZE = 120000
  with open(src, 'rb') as src, open(dst, 'wb') as fdst:
     # prevent loading too much data to memory
     for n,x in enumerate(iter(lambda: src.read(BUFF_SIZE),"")):
        fdst.write(x)

显然,这会将一个文件的内容复制到另一个文件,似乎比类似的实现快一点。您可以将buff大小更改为要加载到内存的任何大小