我正在阅读格式化的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是我想要的那个,并读取/解码返回数据的字段。如果该字段不是我想要的字段,它会读取行,直到它到达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替换上面的内容,然后读取返回的字符串......
我看过this post,不过我的问题稍微宽泛一点(帖子想要一个行号。我想要一个字节偏移)。看起来这可以通过使用流访问和pos说明符的一些魔法来完成,但我不确定这是否会迫使我完全重写读者(这几乎是不可能的,因为我不知道读者如何实际上将看似随机的字符串转换为浮点数。)
答案 0 :(得分:2)
格式化流访问(在Fortran 2003标准中引入)允许您在文件中寻找先前已读过的位置。由于格式化的流仍然具有基于记录的方法(正式使用换行符作为记录分隔符),因此通常可以重复使用用于格式化顺序访问的相同代码。
使用INQUIRE语句获取当前文件位置:
INTEGER :: file_pos
INQUIRE(UNIT=iu, POS=file_pos)
您可以在读取包含每个fieldname
行的记录之前以这种方式调用INQUIRE,然后读取该记录,确定该记录的字段名是什么,并将字段名和文件位置存储在数组中或类似的以便以后查找。
您可以使用不提前的READ:
重新定位到先前存储的位置READ (iu,"()", ADVANCE='NO', POS=file_pos)
随后的READ语句将继续执行,因为它们将用于第一次遇到重新定位记录的顺序格式化文件。