使用Python逐字读取非常大的文件

3

我有一些非常大的文本文件(>2g),我想逐字处理它们。这些文件是以空格分隔的文本文件,没有换行符(所有单词都在一行中)。我想取出每个单词,测试它是否是字典单词(使用enchant),如果是,就将其写入新文件。

这是我现在的代码:

with open('big_file_of_words', 'r') as in_file:
        with open('output_file', 'w') as out_file:
            words = in_file.read().split(' ')
            for word in word:
                if d.check(word) == True:
                    out_file.write("%s " % word)

我看过Python中读取大文件的懒惰方法,它建议使用yield分块读取,但我担心使用预定大小的块会将单词分割在中间。基本上,我希望块尽可能接近指定的大小,同时只在空格处分割。有什么建议吗?

3个回答

6

将一个块的最后一个单词与下一个块的第一个单词合并:

def read_words(filename):
    last = ""
    with open(filename) as inp:
        while True:
            buf = inp.read(10240)
            if not buf:
                break
            words = (last+buf).split()
            last = words.pop()
            for word in words:
                yield word
        yield last

with open('output.txt') as output:
    for word in read_words('input.txt'):
        if check(word):
            output.write("%s " % word)

'last' 用于什么?我们可以不用它吗? - pambda
如果在读取后,buf末尾有一个空格并且在接下来的读取中buf末尾有一个拆分单词,则会出现错误。如果测试文件testfile.txt为:This is a file with some text in it and no newlines. Some text has punctuation. Test this file out with multiple buffer sizes.并且读取大小为20:inp.read(20)则您将看到withsomeandnopunctuation.Test被连接起来。 - MRSharff

1

您可能可以尝试类似于您链接到的问题的答案,但结合remmap,例如:

import mmap
import re

with open('big_file_of_words', 'r') as in_file, with open('output_file', 'w') as out_file:
    mf = mmap.mmap(in_file.fileno(), 0, access=ACCESS_READ)
    for word in re.finditer('\w+', mf):
        # do something

对于OSX用户,您需要更改为access=mmap.ACCESS_READ - Laurent

0

幸运的是,Petr Viktorin已经为我们编写了代码。以下代码从文件中读取一个块,然后对每个包含的单词进行yield。如果一个单词跨越多个块,也会被处理。

line = ''
while True:
    word, space, line = line.partition(' ')
    if space:
        # A word was found
        yield word
    else:
        # A word was not found; read a chunk of data from file
        next_chunk = input_file.read(1000)
        if next_chunk:
            # Add the chunk to our line
            line = word + next_chunk
        else:
            # No more data; yield the last word and return
            yield word.rstrip('\n')
            return

https://dev59.com/FWsz5IYBdhLWcg3wpZvy#7745406


请不要为每个单词翻译,仅返回已翻译的文本。 - siulkilulki

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