代码之家  ›  专栏  ›  技术社区  ›  Saqib Ali

如何迭代使用分号分隔的非常大的文本文件?

  •  0
  • Saqib Ali  · 技术社区  · 6 年前

    如果我想一行一行地迭代一个文本文件,下面是我的方法:

    for curr_line in open('my_file.txt', 'r').readlines()
        print '|' + curr_line + '|'
    

    如果我想重复使用基于分号分隔符的文本,下面是我的方法:

    for curr_line in open('my_file.txt', 'r').read().split(';')
        print '|' + curr_line + '|'
    

    如果我想一行一行地迭代一个非常大的文本文件,下面是我的方法:

    for curr_line in open('my_file.txt', 'r').xreadlines()
        print '|' + curr_line + '|'
    

    但是,如何迭代使用基于分号分隔符的非常大的文本文件?它是7+千兆字节,所以我无法将整个内容读取到内存中。

    下面是示例输入文件 my_file.txt :

    AAAA;BBBBB
    BB;CCC;
    DDDDD
    D
    D;
    EEEE;F
    

    下面是基于上面的代码片段我想看到的输出:

    |AAAA|
    |BBBBB
    BB|
    |CCC|
    |DDDDD
    D
    D|
    |EEEE|
    |F|
    
    2 回复  |  直到 6 年前
        1
  •  1
  •   jedwards    6 年前

    这里有一个“reader”对象,它将从文件中读取块(大小由您选择),并在找到块时发出分号分隔的项:

    class MyReader:
        def __init__(self, handle, delim, read_size=512):
            self.handle = handle
            self.delim = delim
            self.read_size = read_size
    
    
        def __iter__(self):
            buffer = []
            while True:
                block = self.handle.read(self.read_size)
                if not block: break     # Reached EOF
    
                while block:
                    (before, sep, block) = block.partition(self.delim)
                    buffer.append(before)
    
                    if sep:             # Separator was found, yield the buffer
                        yield ''.join(buffer)
                        buffer = []
    
            # We broke free, flush the buffer and return (explicit)
            yield ''.join(buffer)
            return
    

    例如,您可以使用:

    with open('file.txt') as f:
        reader = MyReader(f, ';')
    
        for chunk in reader:
            print(repr(chunk))
    

    输出:

    'AAAA'
    'BBBBB\nBB'
    'CCC'
    '\nDDDDD\nD\nD'
    '\nEEEE'
    'F'
    
        2
  •  1
  •   dawg    6 年前

    方法 .readlines() 将整个文件读取到列表中。使用7GB文件可能不可行。

    在添加的示例中,可以使用 mmap 和一个regex来完成整个文件的regex匹配,而不加载整个文件:

    import re 
    import mmap 
    
    with open(fn,'r+b') as f_in:
        mm = mmap.mmap(f_in.fileno(), 0)    
        for m in re.finditer('([^;]*)', mm):
            txt=m.group(1)
            if txt:
                print('|{}|'.format(txt))
    

    通过示例,打印:

    |AAAA|
    |BBBBB
    BB|
    |CCC|
    |
    DDDDD
    D
    D|
    |
    EEEE|
    |F|
    
    推荐文章