Python:以块的形式读取大文件

时间:2011-05-10 17:27:37

标签: python

嘿那里,我有一个相当大的文件,我想用Python处理,我对如何做到这一点感到困惑。

我的文件格式如下:

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

所以我基本上想要从0-1读取块,对它进行处理,然后转到1和2之间的块。

到目前为止,我已经尝试使用正则表达式匹配数字,然后继续迭代,但我确信必须有更好的方法来解决这个问题。任何建议/信息将不胜感激。

6 个答案:

答案 0 :(得分: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

以及其他代码。

答案 1 :(得分:2)

为什么不用char file.read(1)来读取char文件?

然后,您可以 - 在每次迭代中 - 检查您是否到达了char 1。然后你必须确保存储字符串很快。

答案 2 :(得分:1)

如果“N”只能开始一行,那么为什么不使用“简单”解决方案呢? (听起来这已经完成了,我正在努力加强/支持它; - ))

即,一次只读一行,并构建表示当前N对象的数据。在说N = 0并且加载N = 1之后,将它们一起处理,然后移动到下一对(N = 2,N = 3)。唯一甚至远程棘手的事情就是确保不要丢弃读取线。 (确定结束条件的读取行 - 例如“N” - 也包含下一个N的数据。

除非需要搜索(或禁用IO缓存或每个项目存在大量数据),否则没有理由不使用readline AFAIK。

快乐的编码。


这是一些袖口代码,可能包含多个错误。无论如何,它使用最小化的副作用方法显示了一般的想法。

# 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)

答案 3 :(得分:0)

如果格式是固定的,为什么不用readline()

一次读取3行

答案 4 :(得分:0)

如果文件很小,你可以读取整个文件和split()数字数字(可能想用strip()来删除空格和换行符),然后将列表折叠到处理列表中的每个字符串。您可能必须检查您正在处理的结果字符串最初是否为空,以防两个数字彼此相邻。

答案 5 :(得分:0)

如果文件的内容可以加载到内存中,而这就是你的回答,那么下面的代码(需要定义文件名)可能是一个解决方案。

import re

regx = re.compile('^((\d+).*?)(?=^\d|\Z)',re.DOTALL|re.MULTILINE)

with open(filename) as f:
    text = f.read()

def treat(inp,regx=regx):
    m1  = regx.search(inp)
    numb,chunk = m1.group(2,1)
    li = [chunk]
    for mat in regx.finditer(inp,m1.end()):
        n,ch = mat.group(2,1)
        if int(n) == int(numb) + 1:
            yield ''.join(li)
            numb = n
            li = []
        li.append(ch)
        chunk = ch
    yield ''.join(li)

for y in treat(text):
    print repr(y)

此代码在包含以下内容的文件上运行:

1 mountain
orange 2
apple
produce
2 gas
solemn
enlightment
protectorate
3 grimace
song
4 snow
wheat
51 guludururu
kelemekinonoto
52asabi dabada
5 yellow
6 pink 
music
air
7 guitar
blank 8
8 Canada
9 Rimini

产生

'1 mountain\norange 2\napple\nproduce\n'
'2 gas\nsolemn\nenlightment\nprotectorate\n'
'3 grimace\nsong\n'
'4 snow\nwheat\n51 guludururu\nkelemekinonoto\n52asabi dabada\n'
'5 yellow\n'
'6 pink \nmusic\nair\n'
'7 guitar\nblank 8\n'
'8 Canada\n'
'9 Rimini'