当不知道适当的 RECL 时,如何使用 Fortran 未格式化的直接访问访问单个记录?

How to access a single record with Fortran unformatted direct-access when the appropriate RECL is not known?

除非使用 F2003 中可用的新式流访问,否则 Fortran 传统上将文件视为一系列记录。如果文件被连接为直接访问,则可以通过指定记录号以任何顺序访问任何记录。例如:

open(newunit=funit, file=filename, form='unformatted', access='direct', &
     recl=64, status='old')
read(funit, rec=2) data
close(funit)

这听起来不错...但是,我不确定我是否理解 RECL 参数以及在不知道正确的记录长度的情况下如何有效地使用直接访问。来自文档(各种英特尔 Fortran 版本):

All records have the length specified by the RECL option in the OPEN statement.

换句话说,直接访问允许访问等于或小于 RECL 的数据 ,同时以 RECL 的增量在文件中移动。也就是说,您可以指定任何您喜欢的值(我假设等于或小于文件的大小)。我想这在事后看来是显而易见的……但我希望可以通过某种方式发现适当的 RECL。1 也许我做错了,但我只想从指定的记录中获取数据——不多也不少。

除了在文件的 'header' 部分中对适当的 RECL 值进行编码之外,有没有一种方法可以在连接未格式化(甚至格式化)的文件时一次访问单个记录) 如果事先不知道正确的记录长度是否直接访问?使用了哪些交易技巧来做到这一点?

1 我曾希望 inquire(funit, recl=rl) 会提供适当的 RECL,但如果文件是为直接访问而连接的,它 returns 打开文件时指定的 RECL 值。如果连接顺序访问,似乎它 returns 允许的最大记录长度(?),在我的例子中是 2040。

事实上,不可能通过查看文件找到它,因为那只是数据并且(通常)没有记录标记,因此编译器只看到非结构化字节流。至少在面向字节的计算机中。我对面向记录的文件系统一无所知,只知道它们存在。

如果你知道直接访问记录中存储了什么样的数据,你可以通过询问数据而不是文件来询问编译器。

例如,如果记录由变量abc组成,无论它们是什么,

 !just an example
 real :: a(10)
 type(my_type) :: b
 character(5) :: c(3)

你问这样的记录有多大

 inquire(iolength=rl) a, b, c

然后将文件与 recl=rl

连接
open(newunit=funit, file=filename, form='unformatted', access='direct', &
     recl=rl, status='old')

参见,例如,

请注意,RECL 值不可移植, 因编译器而异。有些以字节为单位,有些以 4 字节字为单位。我只记得 gfortran 和 ifort 不同,不知道哪个是哪个。我不在乎哪个是哪个。

如果您发现自己像在 recl=64 中那样使用魔术常量指定 RECL,那么您做错了什么,因为这在不同的编译器中不起作用。你应该总是有一个变量,而不是一个固定的数字。