在不解压的情况下逐行读取80GB .gz文件的内容

3
6个回答

6
你可以使用zcat来将未压缩的内容流式传输到grep或任何你想要的过滤器中,而不会产生空间开销。例如:
zcat bigfile.gz | grep PATTERN_I_NEED > much_smaller_sample

此外,如果你只是在流式传输到grep,你可以使用zgrep,例如:
zgrep PATTERN_I_NEED bigfile.gz > much_smaller_sample

但是在某些系统上,zgrep 并不支持 grep 的全部功能。


1
我写了一个小的Python脚本来代替grep,但它可以与zcat完美地配合使用。谢谢! - user692734

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

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

快速演示:

>>> 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() 函数来从读取器中一次获取一行数据,但是使用读取器的原理与在循环中使用相同。
上述方法几乎不占用内存;只有几千字节的文件缓冲区和当前块需要解压缩,以及 row 列表中的 Python 字符串。

0

很不幸,你需要从头开始解压缩。然而,你不需要一次性将所有内容读入内存。据我记得,Python的实现是将内容读入内存的,但你可以作为外部工具运行gzip,并将其stdout作为csv读取器的数据源。这样做的好处是可以在单独的处理器中并行解压缩。


0
如果你想使用Python,请看一下gzip。前提是与迭代常规文本文件相同,即:
import gzip
gz = gzip.GzipFile('/path/file.gz')
for i in gz:
    print(i)


-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)

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接