Python: 分块读取大文件

4 投票
6 回答
9651 浏览
提问于 2025-04-16 17:22

你好,我有一个比较大的文件想用Python来处理,但我有点不知道该怎么做。

我的文件格式是这样的:

0 xxx xxxx xxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
1 xxx xxxx xxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

简单来说,我想先读取从0到1的这一部分,处理完后再继续读取1到2之间的部分。

到目前为止,我尝试用正则表达式来匹配数字,然后不断迭代,但我觉得肯定有更好的方法来实现这个。任何建议或信息都非常感谢。

6 个回答

1

如果"N "只能在行的开头出现,那为什么不直接用“简单”的方法呢?(听起来这个方法已经有人在用了,我只是想支持一下这个想法;-

也就是说,可以一次读取一行,然后构建当前N对象的数据。比如说,当N=0和N=1加载完后,就一起处理它们,然后再继续下一个对(N=2,N=3)。唯一需要注意的就是不要丢掉读取的行。(决定结束条件的那一行,比如"N ",也包含了下一个N的数据)。

除非需要查找(或者输入输出缓存被禁用,或者每个项目的数据量非常大),否则我觉得没有理由不使用readline。

祝编码愉快。


这里有一些随意写的代码,可能包含多个错误。不过,它展示了使用最小副作用的方法的一般思路。

# given an input and previous item data, return either
# [item_number, data, next_overflow] if another item is read
# or None if there are no more items
def read_item (inp, overflow):
  data = overflow or ""

  # this can be replaced with any method to "read the header"
  # the regex is just "the easiest". the contract is just:
  # given "N ....", return N. given anything else, return None
  def get_num(d):
    m = re.match(r"(\d+) ", d)
    return int(m.groups(1)) if m else None

  for line in inp:
    if data and get_num(line) ne None:
      # already in an item (have data); current line "overflows".
      # item number is still at start of current data
      return [get_num(data), data, line]

    # not in item, or new item not found yet
    data += line

  # and end of input, with data. only returns above
  # if a "new" item was encountered; this covers case of
  # no more items (or no items at all)
  if data:
    return [get_num(data), data, None]
  else
    return None

用法可能类似于下面的例子,其中f代表一个打开的文件:

# check for error conditions (e.g. None returned)
# note feed-through of "overflow"
num1, data1, overflow = read_item(f, None)
num2, data2, overflow = read_item(f, overflow)
2

你为什么不直接用 file.read(1) 一次读取一个字符呢?

这样的话,在每次读取的时候,你可以检查一下是不是读到了字符 1。然后你还得确保存储这个字符串的速度要快。

3

如果它们都在同一行,也就是说“1.”和“2.”之间没有换行符,那么你可以像这样遍历文件的每一行:

for line in open("myfile.txt"):
    #do stuff

在每次循环时,这一行会被处理掉并被覆盖,这样你就可以轻松处理大文件。如果它们不在同一行:

for line in open("myfile.txt"):
    if #regex to match start of new string
       parsed_line = line
    else:
       parsed_line += line

以及你代码的其他部分。

撰写回答