除非使用 F2003 中可用的新流访问,否则 Fortran 通常将文件视为记录序列。如果文件连接为直接访问,则可以通过指定记录号以任何顺序访问任何记录。例如:
open(newunit=funit, file=filename, form='unformatted', access='direct', &
recl=64, status='old')
read(funit, rec=2) data
close(funit)
所以这听起来很棒...但是,我不确定我是否理解 RECL 参数以及在不知道正确的记录长度的情况下如何有效地使用直接访问。来自文档(各种 Intel 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,但如果连接文件以进行直接访问,则返回打开文件时指定的 RECL 值。如果连接进行顺序访问,它似乎返回允许的最大记录长度(?),在我的例子中为 2040。
最佳答案
事实上,通过查看文件是不可能找到它的,因为那只是数据并且(通常)没有记录标记,因此编译器只看到非结构化字节流。至少在面向字节的计算机中是这样。我对面向记录的文件系统一无所知,只知道它们存在。
如果您知道直接访问记录中存储了什么样的数据,则可以通过询问数据而不是文件来询问编译器。
例如,如果记录由变量 a
、b
、c
组成,无论它们是什么,
!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')
例如,参见 Why direct access I/O works incorrectly with Intel Visual Fortran
请注意,RECL 值不可移植,并且会因编译器而异。有些以字节为单位,有些以 4 字节字为单位。我只记得 gfortran 和 ifort 不同,而不是哪个是哪个。我不在乎哪个是哪个。
如果您发现自己使用魔术常量指定 RECL,如 recl=64
所示,那么您就做错了,因为这在其他编译器中不起作用。您应该始终有一个变量,而不是固定数字。
关于fortran - 当不知道适当的 RECL 时,如何使用 Fortran 无格式直接访问来访问单个记录?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43898711/