我有一个很大的文本文件要解析。主要模式如下:
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 为给定的形状。
我已经做了一些编程......主要思想是
- 首先获取每个分隔符的偏移量(“步骤 X”)
- 跳过 nX (n1, n2...) 行 + 1 以到达数据
- 从那里一直读取字节到下一个分隔符。
一开始我想避免使用正则表达式,因为这些会大大减慢速度。完成第一步已经需要 3-4 分钟(浏览文件以获取每个部分的偏移量)。
问题是我基本上是使用file.tell()
方法来获取分隔符位置:
[file.tell() - len(sep) for line in file if sep in line]
问题有两个方面:
- 对于较小的文件,
file.tell()
给出正确的分隔符位置,对于较长的文件,它没有。我怀疑file.tell()
不应该在循环中使用,既不使用显式file.readline()
也不使用隐式for line in file
(我都尝试过)。我不知道,但结果就在那里:对于大文件,[file.tell() for line in file if sep in line]
没有系统地给出分隔符后行的位置。 - 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()
在隐式循环中使用时,我没有得到当前位置,而是缓冲区的结尾。这只是一个疯狂的猜测。