Как перебрать очень большой текстовый файл через точку с запятой? - PullRequest
0 голосов
/ 12 октября 2018

Если я хочу перебирать текстовый файл построчно, вот как я это делаю:

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 ]

0 голосов
/ 12 октября 2018

Вот объект «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'
0 голосов
/ 12 октября 2018

Метод .readlines() считывает весь файл в список.Это может оказаться невозможным для файла размером 7 ГБ.

Учитывая добавленный пример, вы можете использовать mmap и регулярное выражение для сопоставления регулярного выражения всего файла без загрузки всего файла:

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