2

我正在阅读格式化的 ascii 文件。该文件本质上是 ascii 编码的,看起来像这样:

fieldname 1
header info 1
header info 2
header info 3
aruieopaurjjk&*(^0uio3789$
#$adsfhoueraeiknvaer93-8(&897klfaicvnjai9ea890 34
*(()kla3j90ajkl4a8 ...

fieldname 2
header info 1
header info 2
header info 3
8&80973jknaua890a3a()Ujkl;fjaoi0()8&*(&jla;f)*(
jkl;aje()()78907jkoja0988093jn890&*(4fakoa343a
...

因此,虽然文件是 ascii,但它们不是人类可读的。记录长度不一致。假设文件指针位于之前,我有例程来读取数据fieldname。它检查以确保字段名是我想要的,并读取/解码返回数据的字段。如果该字段不是我想要的,它会读取行,直到出现fieldname线。可以想象,这是非常低效的。要读取最后一个字段,我基本上需要按顺序读取所有其他字段。另外,如果我乱读它们,我需要倒回整个文件并重新开始。我想做的是创建一个索引,以便我可以将字段名映射到文件开头的字节偏移量。这样,我就可以“寻找”文件中的正确位置并继续作为格式化的顺序文件读取......

我对任何允许我通过以下方式读取文件的解决方案感到满意:

read(iu,'(A)',end=190) mystring  !get from current position to end of line
read(iu,*,end=190) myint1,myint2 !read two integers
read(iu,'(a,i8,3e14.7,i8,a)',end=190, err=900) !read a string, 8 character wide integer ...

我什至可以接受具有某种优化getline功能和流访问的解决方案。然后我可以用对 getline 的调用替换上面的内容,然后读取返回的字符串......

我看过这篇文章,但是我的问题稍微笼统一些(那篇文章想要一个行号。我想要一个字节偏移量)。似乎这可以通过使用流访问和 pos 说明符的一些魔法来完成,但我不确定这是否会迫使我完全重写阅读器(这几乎是不可能的,因为我不知道阅读器如何实际上将看似随机的字符串转换为浮点数)。

4

1 回答 1

4

格式化流访问(在 Fortran 2003 标准中引入)允许您查找文件中先前已读取的位置。因为格式化流仍然具有基于记录的方法(正式使用换行符作为记录分隔符),所以通常可以重用用于格式化顺序访问的相同代码。

使用 INQUIRE 语句获取当前文件位置:

INTEGER :: file_pos
INQUIRE(UNIT=iu, POS=file_pos)

您可以在读取包含每一行的记录之前以这种方式调用 INQUIRE fieldname,然后读取该记录,确定该记录的字段名,并将字段名和文件位置存储在数组或类似文件中以供以后查找。

您可以使用非前进 READ 重新定位到先前存储的位置:

READ (iu,"()", ADVANCE='NO', POS=file_pos)

随后的 READ 语句将继续执行,就像它们对第一次遇到重新定位的记录的顺序格式化文件一样。

于 2012-08-02T21:07:59.720 回答