从 fortran 写出二进制文件并读取 C 语言
Writing out a binary file from fortran and reading in C
我正在尝试读取从fortran程序生成的二进制文件。 我的输出中出现了奇怪的字符,难道 fortran 和 C 都有不同的 endianess?
使用
acces="stream"
而不是未格式化。它直接以C I/O建模,因此理解它应该没有任何问题。它是Fortran 2003的一部分,所有现代编译器都实现了AFAIK(即使是Open64或NEC等不太先进的编译器)。
Fortran 和 C 在同一台计算机上使用相同的字节序,除非您使用特殊的编译器功能。在平台之间传输文件时可能会出现问题。
如果 Fortran 程序使用
access="sequential", form="unformatted"
您将在使用记录分隔符时遇到问题。
写入为
的文件 access="direct", form="unformatted"
可以没事。
Fortran 在其二进制文件中放置了一个标头,因此您只能使用 Fortran 直接读取它们。在 Fortran 中写入二进制文件时,请使用form='unformatted'
以避免这种情况。此处显示了读取无格式二进制文件的方法。为了更深入地了解 Fortran 如何处理二进制 I/O,一个很好的起点是这种威胁。
正如其他人(@cup)所问的那样,您是如何编写文件的?
Fortran 和 C 之间的 IO 可以很好地配合使用,正如 @Vladimir 所说,在编写时要小心字节序。如果不指定,它们都应该是本机写入/读取。它可以是编译器选项,也可以是 Fortran 中open
的选项。
例如
- 伊福特:
-convert big_endian
- 格福特兰:
-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 <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
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 != %dn", 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: %d j: %d x: %fn", 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
)例程。
- 理解boost::asio-async_read在无需读取内容时的行为
- 使用新行和不使用新行读取文件
- 读取文件并输入到矢量中
- 用c++从输入文件中读取另一行
- 读取文件的最后一行并输入到链接列表时出错
- 在进程中对同一管道进行读取和写入时C++管道出现问题
- 无法找到/读取配置文件.conf-FileIOException
- 如何使用Luacneneneba API正确读取字符串和表参数
- C++将文本文件中的数据读取到结构数组中
- 我如何使用GO语言读取可能是两种不同数据类型之一的HDF5属性
- 从 .glsl 文件中读取 OpenGL 着色器语言
- 从 fortran 写出二进制文件并读取 C 语言
- 将C++结构写入文件并使用另一种编程语言读取文件
- 在c语言中第二次读取文件时程序崩溃
- 如何从C语言的第二行读取字符串文件
- 如何在C语言中读取导入目录表
- 有效地从字符串中读取两个逗号分隔的浮点数,而不受全局语言环境的影响
- 在C语言中从文本文件中读取特定的数据列
- 从文本文件中读取数据,并使用c++语言将其存储在二维矢量中
- 非 unicode 程序的语言会更改 ini 读取