1

我有一个很大的文本文件要解析。主要模式如下:

step 1

[n1 lines of headers]

  3  3  2
 0.25    0.43   12.62    1.22    8.97
12.89   89.72   34.87   55.45   17.62
 4.25   16.78   98.01    1.16   32.26
 0.90    0.78   11.87
step 2

[n2 != n1 lines of headers]

  3  3  2
 0.25    0.43   12.62    1.22    8.97
12.89   89.72   34.87   55.45   17.62
 4.25   16.78   98.01    1.16   32.26
 0.90    0.78   11.87
step 3

[(n3 != n1) and (n3 !=n2) lines of headers]

  3  3  2
 0.25    0.43   12.62    1.22    8.97
12.89   89.72   34.87   55.45   17.62
 4.25   16.78   98.01    1.16   32.26
 0.90    0.78   11.87

换句话说:

分隔符:步骤#

已知长度的标头(行号,而不是字节)

数据3维形状:nz、ny、nx

数据:fortran 格式,原始数据集中约 10 个浮点数/行

我只想提取数据,将它们转换为浮点数,将其放入一个 numpy 数组中,然后将其 ndarray.reshape 为给定的形状。

我已经做了一些编程......主要思想是

  1. 首先获取每个分隔符的偏移量(“步骤 X”)
  2. 跳过 nX (n1, n2...) 行 + 1 以到达数据
  3. 从那里一直读取字节到下一个分隔符。

一开始我想避免使用正则表达式,因为这些会大大减慢速度。完成第一步已经需要 3-4 分钟(浏览文件以获取每个部分的偏移量)。

问题是我基本上是使用file.tell()方法来获取分隔符位置:

[file.tell() - len(sep) for line in file if sep in line]

问题有两个方面:

  1. 对于较小的文件,file.tell()给出正确的分隔符位置,对于较长的文件,它没有。我怀疑file.tell()不应该在循环中使用,既不使用显式file.readline()也不使用隐式for line in file(我都尝试过)。我不知道,但结果就在那里:对于大文件,[file.tell() for line in file if sep in line]没有系统给出分隔符后行的位置。
  2. len(sep) 没有给出正确的偏移校正以返回“分隔符”行的开头。sep是一个字符串(字节),包含文件的第一行(第一个分隔符)。

有谁知道我应该如何解析?

注意:我首先找到偏移量,因为我希望能够在文件中浏览:我可能只想要第 10 个数据集或第 50000 个数据集......

1-找到偏移量

sep = "step "
with open("myfile") as f_in:
    offsets = [fin.tell() for line in fin if sep in line]

正如我所说,这适用于简单的示例,但不适用于大文件。

新测试:

sep = "step "
offsets = []
with open("myfile") as f_in:
    for line in f_in:
        if sep in line:
            print line
            offsets.append(f_in.tell())

打印的行对应于分隔符,这是毫无疑问的。但是获得的偏移量与f_in.tell()下一行不对应。我猜该文件缓冲在内存中,当我尝试f_in.tell()在隐式循环中使用时,我没有得到当前位置,而是缓冲区的结尾。这只是一个疯狂的猜测。

4

1 回答 1

0

我得到了答案:for在文件上循环,相处得不tell()太好。就像混合for i in filefile.readline()引发错误一样。

所以,使用file.tell()with file.readline()or file.read() only

永远不要使用

for line in file:
    [do stuff]
    offset = file.tell()

这确实是一种耻辱,但事实就是如此。

于 2013-03-25T14:59:08.017 回答