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

荒凉一梦 提交于 2020-01-04 06:56:17

问题


Unless using the new-ish stream-access available in F2003, Fortran classically considers files to be a sequence of records. If a file is connected for direct-access one can access any record in any order by specifying the record number. For example:

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

So this sounds great...however, I'm not sure I understand the RECL parameter and how direct-access can be used effectively if the correct record length isn't already known. From the docs (various Intel Fortran versions):

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

In other words, direct-access allows access to data in an amount equal to or less than RECL, while moving through the file in increments of RECL. That is, you can specify any value you like (equal to or less than the size of the file, I assume). I guess that's obvious in hindsight...yet I was hoping that the appropriate RECL was discoverable in some way.1 Perhaps I'm doing this wrong, but I would like to get the data from the specified record only - not more, not less.

Aside from encoding the appropriate RECL value in a 'header' section of the file, is there a way to access a single record at a time with a file connected for unformatted (or even formatted) direct-access if the correct record length is not known beforehand? What tricks-of-the-trade are used to do this?

1 I had hoped inquire(funit, recl=rl) would provide the appropriate RECL, but if the file was connected for direct-access, it returns the RECL value specified when the file was opened. If connected for sequential-access, it seems that it returns the maximum record length allowed (?), 2040 in my case.


回答1:


Indeed, it is not possible to find it out from looking at the file, because that is just the data and (normally) no record markers, so the compiler just sees a stream of unstructured bytes. At least in byte oriented computers. I know nothing about record oriented filesystems, only that they exist.

If you know what kind of data is stored in the direct access record, you can inquire the compiler by asking not about the file, but about the data.

For example, if the record consists of variables a, b, c, whatever they are,

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

you ask how large such a record is

 inquire(iolength=rl) a, b, c

and then you connect your file with recl=rl

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

See, for example, Why direct access I/O works incorrectly with Intel Visual Fortran

Be careful, the RECL value is not portable and will vary between compilers. Some measure it in bytes and some in 4-byte words. I just remember that gfortran and ifort differ, not which one is which. And I don't care which one is which.

If you find yourself specifying RECL with a magic constant as in recl=64 you are doing something wrong, because this will not work in a different compiler. You should always have a variable, not a fixed number.



来源:https://stackoverflow.com/questions/43898711/how-to-access-a-single-record-with-fortran-unformatted-direct-access-when-the-ap

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!