16

我有一个文件,其中使用分隔符分隔行 say .。我想逐行读取这个文件,其中行应该基于存在.而不是换行符。

一种方法是:

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

但是如果我的文件太大,这不是内存效率。我不想一起阅读整个文件,而是想逐行阅读。

open支持参数“换行符”,但此参数仅None, '', '\n', '\r', and '\r\n'作为此处提到的输入。

有没有办法有效地读取文件行但基于预先指定的分隔符?

4

3 回答 3

22

您可以使用生成器:

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
于 2013-04-28T06:10:07.520 回答
3

这是一个更有效的答案,使用FileIObytearray我用于解析 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):
         ...
于 2018-12-10T10:56:34.013 回答
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
于 2013-05-07T23:15:45.763 回答