io – 读取未格式化的二进制文件:意外的输出 – Fortran90

前言:我需要弄清楚二进制grid_data_file的结构.从Fortran例程中我发现第一条记录由57个字节组成,并按以下顺序包含信息.

No. of the file :: integer*4
File name :: char*16
file status :: char*3 (i.e. new, old, tmp)
.... so forth (rest is clear from write statement in the program)

现在进行测试我写了一个简单的程序如下:(我没有包含所有参数)

Program testIO
  implicit none

  integer :: x, nclat, nclon
  character :: y, z
  real :: lat_gap, lon_gap, north_lat, west_lat
  integer :: gridtype

  open(11, file='filename', access='direct', form='unformatted', recl='200')

  read(11, rec=1) x,y,z,lat_gap,lon_gap, north_lat,west_lat, nclat, nclon, gridtyp
  write(*,*) x,y,z,lat_gap,lon_gap, north_lat,west_lat, nclat, nclon, gridtyp

  close(11)
END

令我惊讶的是,当我将声明部分更改为

  integer*4 :: x, nclat, nclon
  character*16 :: y
  character*3 :: z
  real*4 :: lat_gap, lon_gap, north_lat, west_lat
  integer*2 :: gridtype

它给了我一些正确的信息,尽管不是全部!我无法理解这一点.如果有人解释这种现象,它将有助于我提高我的Fortran知识.

此外,我不能使用ACCESS = stream由于机器老旧而不支持,所以我得出结论,上面是唯一可能找出文件结构.

最佳答案 从您的回复和其他人的评论中,我认为您的问题可能是对Fortran“记录”的误解:

你说你有一个二进制文件,其中每个条目(你说的记录,但稍后更多)是57个字节.

问题是Fortran I / O中的“记录”并不是您所期望的来自C(或其他任何地方,真正的)背景.请参阅英特尔的以下文档,该文档对不同的访问模式给出了很好的解释:

> https://software.intel.com/sites/products/documentation/hpc/composerxe/en-us/2011Update/fortran/lin/bldaps_for/common/bldaps_rectypes.htm

简而言之,它具有描述每个条目中数据的额外数据(标题).

Moreover, I can’t use ACCESS=stream due to machine being old and not supported, so I conclude that above is the only possibility to figure out the file structure. Any guidance would be a big help!

如果你不能使用流,AFAIK真的没有简单而无痛的方法来读取没有记录信息的二进制文件.

需要C编译器的可能解决方案是在您从Fortran调用的C函数中执行IO,“最小”示例:

main.f90时:

program main
integer, parameter :: dp = selected_real_kind(15)
character(len=*), parameter :: filename = 'test.bin'
real(dp) :: val
call read_bin(filename, val)
print*, 'Read: ', val
end program

read.c:

#include <string.h>
#include <stdio.h>

void read_bin_(const char *fname, double *ret, unsigned int len)
{
    char buf[256];
    printf("len = %d\n", len);
    strncpy(buf, fname, len);
    buf[len] = '\0'; // fortran strings are not 0-terminated
    FILE* fh = fopen(buf, "rb");
    fread(ret, sizeof(double), 1, fh);
    fclose(fh);
}

请注意,由于Fortran处理字符串的方式,最终需要一个额外的参数和一些字符串操作,这与C不同.

为write.c:

#include <stdio.h>

int main() {
    double d = 1.234;
    FILE* fh = fopen("test.bin", "wb");
    fwrite(&d, sizeof(double), 1, fh);
    fclose(fh);
}

编制说明:

gcc -o write write.c
gcc -c -g read.c
gfortran -g -o readbin main.f90 read.o

使用./write创建二进制文件,然后查看Fortran代码如何使用./readbin读取它.

这可以针对不同的数据类型进行扩展,以基本上模拟access = stream.最后,如果你可以重新编译原始的Fortran代码以不同的方式输出数据文件,这将是最简单的解决方案,因为这是一个粗暴的黑客.

最后,获取未知数据格式的提示:工具od是您的朋友,请查看其联机帮助页.它可以直接将二进制represantations转换为各种不同的本机数据类型.试试上面的例子(z在右栏中添加了字符表示,在这里不是很有用,一般是的):

od -t fDz test.bin
点赞