Подтвердить что ты не робот

Чтение файла с указанным разделителем для новой строки

У меня есть файл, в котором строки разделяются с помощью деминера .. Я хочу прочитать этот файл за строкой, где строки должны быть основаны на наличии . вместо новой строки.

Один из способов:

f = open('file','r')
for line in f.read().strip().split('.'):
   #....do some work
f.close()

Но это не так эффективно, если мой файл слишком большой. Вместо того, чтобы читать весь файл вместе, я хочу его читать по строкам.

open поддерживает параметр 'newline', но этот параметр принимает None, '', '\n', '\r', and '\r\n' как входной, как указано здесь.

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

4b9b3361

Ответ 1

Вы можете использовать генератор:

def myreadlines(f, newline):
  buf = ""
  while True:
    while newline in buf:
      pos = buf.index(newline)
      yield buf[:pos]
      buf = buf[pos + len(newline):]
    chunk = f.read(4096)
    if not chunk:
      yield buf
      break
    buf += chunk

with open('file') as f:
  for line in myreadlines(f, "."):
    print line

Ответ 2

Самый простой способ - предварительная обработка файла для создания новых строк, где вы хотите.

Вот пример использования perl (если вы хотите, чтобы строка "abc" была новой строкой):

perl -pe 's/abc/\n/g' text.txt > processed_text.txt

Если вы также хотите игнорировать исходные символы новой строки, используйте вместо этого следующее:

perl -ne 's/\n//; s/abc/\n/g; print' text.txt > processed_text.txt

Ответ 3

Вот более эффективный ответ, используя FileIO и bytearray, который я использовал для разбора файла PDF -

import io
import re


# the end-of-line chars, separated by a '|' (logical OR)
EOL_REGEX = b'\r\n|\r|\n'  

# the end-of-file char
EOF = b'%%EOF'



def readlines(fio):
    buf = bytearray(4096)
    while True:
        fio.readinto(buf)
        try:
            yield buf[: buf.index(EOF)]
        except ValueError:
            pass
        else:
            break
        for line in re.split(EOL_REGEX, buf):
            yield line


with io.FileIO("test.pdf") as fio:
    for line in readlines(fio):
        ...

Приведенный выше пример также обрабатывает пользовательский EOF. Если вы не хотите этого, используйте это:

import io
import os
import re


# the end-of-line chars, separated by a '|' (logical OR)
EOL_REGEX = b'\r\n|\r|\n'  


def readlines(fio, size):
    buf = bytearray(4096)
    while True:
        if fio.tell() >= size:
            break               
        fio.readinto(buf)            
        for line in re.split(EOL_REGEX, buf):
            yield line

size = os.path.getsize("test.pdf")
with io.FileIO("test.pdf") as fio:
    for line in readlines(fio, size):
         ...