从fortran写出二进制文件并在C中读取

我正在尝试读取一个由fortran程序生成的二进制文件。 我的输出中有一些奇怪的字符,难道这两个fortran和C都有不同的endianess吗?

你应该用

acces="stream" 

而且没有格式化。 它是在CI / O之后直接建模的,因此理解它不会有任何问题。 它是Fortran 2003的一部分,所有现代编译器都实现了它AFAIK(即使是像Open64或NEC那样不太先进)。

除非您使用特殊的编译器function,否则Fortran和C在同一台机器上使用相同的字节顺序。 在平台之间传输文件时可能会出现问题。

如果使用Fortran程序

  access="sequential", form="unformatted" 

你会遇到记录分隔符的问题。

写成的文件

  access="direct", form="unformatted" 

可以。

Fortran在其二进制文件中放置一个标头,因此您只能使用Fortran直接读取它们。 在Fortran中编写二进制文件时使用form='unformatted'来避免这种情况。 这里显示了读取未格式化二进制文件的方法。 为了更深入地了解Fortran如何处理二进制I / O,一个好的起点就是这种威胁 。

正如其他人(@cup)问的那样,你是怎么写这个文件的?

Fortran和C之间的IO可以很好地结合在一起,因为@Vladimir在写作时要小心使用endianess。 如果你没有指明它们都应该是本地写/读。 它可以是编译器选项或在Fortran中open的选项。

例如

  • Ifort: – -convert big_endian
  • Gfortran: -fconvert=big_endian
  • PGI: -byteswapio

等等。 请参考您的编译器手册,找出它的标志。

所以我们假设您按如下方式编写文件:

 program w implicit none integer, parameter :: max_i = 10 integer, parameter :: max_j = 10 integer :: i, j integer :: iunit, stat real :: x(max_i,max_j) do j=1,max_j do i=1,max_i x(i,j) = (i - 1) + (j -1)*max_i end do end do iunit = 7 open(unit=iunit, file="data", iostat=stat, & form="unformatted") if (stat .ne. 0) then write(*,*) "unable to create data file" stop 1 end if write(iunit) x close(iunit) end program w 

如果我们不看文件,

-rw-r--r-- 1 tbrown users 408 Nov 15 13:16 data

注意它是408字节。 正如@leeladam所说,Fortran通常在数据的开头和结尾放置一个大小标题,在这种情况下,它使用4字节记录标记。 因此,两个记录标记和100个数据元素为4字节浮点数:

 2 * 4 + (10*10*4) = 408 

对数据文件进行良好的健全性检查。

然后你可以用C读取它:

 #include  #include  #include  #include  #include  #include  int main(int argc, char **argv) { int ifd = 0; int i = 0; int j = 0; int max_i = 10; int max_j = 10; int fsize = 0; int size = 0; int ierr = 0; float x[max_i][max_j]; if ((ifd = open("data", O_RDONLY)) < 0) { perror("Unable to open data"); return(EXIT_FAILURE); } /* read the data size at the start */ if ((ierr = read(ifd, &fsize, 1*sizeof(int))) < 0) { perror("Size read error"); close(ifd); return(EXIT_FAILURE); } /* compute the size of our data variable */ size = max_i * max_j * sizeof(float); /* read the data */ if (fsize != size) { printf("file and data size mismatch: %d != %d\n", fsize, size); close(ifd); return(EXIT_FAILURE); } if ((ierr = read(ifd, &x, size)) < 0) { perror("Data read error"); close(ifd); return(EXIT_FAILURE); } /* read the data size at the end */ if ((ierr = read(ifd, &fsize, 1*sizeof(int))) < 0) { perror("Size read error"); close(ifd); return(EXIT_FAILURE); } close(ifd); for (i = 0; i <= max_i -1; ++i) { for (j = 0; j <= max_j -1; ++j) { printf("i: %dj: %dx: %f\n", i, j, x[i][j]); } } return(EXIT_SUCCESS); } 

另请注意,您可以使用od检查文件。

要查看第一个记录标记:

 $ od -d -N 4 data 0000000 400 0 0000004 

要查看数据:

 $ od -j 4 -N 400 -f data 0000004 0.000000e+00 1.000000e+00 2.000000e+00 3.000000e+00 0000024 4.000000e+00 5.000000e+00 6.000000e+00 7.000000e+00 0000044 8.000000e+00 9.000000e+00 1.000000e+01 1.100000e+01 

编辑

我忘了提一下,我更喜欢将Fortran二进制输出写成大端并将其记录下来以便人们总是知道。 然后在C中使用xdr (或ntohl )例程。