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