gpt4 book ai didi

c++ - 在 C++ 中读取直接访问 Fortran 未格式化的文件

转载 作者:行者123 更新时间:2023-11-28 02:27:25 24 4
gpt4 key购买 nike

我目前正在尝试用 C++ 读取 Fortran 编写的二进制文件,但没有取得太大成功。写入文件的 Fortran 代码不是我自己的,尽管 C++ 解析例程是。

二进制文件的第一条记录已使用以下语句写入:

INTEGER var1 var2 var3
WRITE(12,REC=1) var1,var2,var3

执行成功读取的 Fortran 片段如下所示:

open(unit=10,file="ETC.bin",access='direct',recl=24,iostat=iost,status='old')
read (unit=10,rec=1) var1,var2,var3
close(unit=10)
print*,var1,var2,var3

在 C++ 方面,到目前为止,我已经得出以下结论:

FILE* binfile = fopen("ETC.bin","rb") ;
fseek (binfile,0,SEEK_END) ;
long lSize = ftell (binfile) ;
char* buffer = (char*) malloc (sizeof(char)*lSize) ;
rewind (binfile) ;
size_t result=fread(buffer,1,96,binfile) ;
for (unsigned i = 0; i<=result; i++){
printf("%f\n",buffer[i]) ;
}

不幸的是,我的 C++ printf 语句返回了无意义的内容。请注意,我假设 Fortran 依赖于 4 位字(例如 gfortran 编译器),并且如果使用 ifort,

--assume byterecl

编译时需要选项。

我知道结果应该是什么,但我不确定如何在 C++ 中复制 Fortran 读取语句的行为。

感谢所有帮助!

附言这里有一个类似的问题:reading fortran binary file in c++ ,它指向以下 dead link .那里的信息不多,或者我的 Google-Fu 很糟糕。

最佳答案

我不是很擅长 C,但我尝试了一些东西。

首先是 Fortran 部分:

program direct_access
implicit none
integer, parameter :: UNT = 63347
open(unit=UNT, file='delme.unf', access='DIRECT', &
form='UNFORMATTED', status='REPLACE', recl=24)
write(UNT, rec=1) 1, 2, 3
write(UNT, rec=2) 4, 5, 6
close(UNT)
end program direct_access

我正在将 3 个整数(每个 4 个字节)写入一个记录长度为 24 字节的未格式化文件。 (注意:我在这里假设记录长度以字节为单位,显然这不能保证并且取决于编译器和系统。)

另外,来自 my preferred Fortran book

Unformatted direct addess files are both smaller and faster than formatted direct access files, but they are not portable between different types of processors.

(除非在打开文件时特别给出FORM='FORMATTED',否则它将是无格式的。)

测试数据是否写入正确:

$ hexdump delme.unf
0000000 0001 0000 0002 0000 0003 0000 0000 0000
0000010 0000 0000 0000 0000 0004 0000 0005 0000
0000020 0006 0000 0000 0000 0000 0000 0000 0000
0000030

看起来不错。注意记录长度(24字节)大于数据(3*4字节),所以里面有未使用的数据 block 。

现在是 C 程序,不是我的专长:

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>

off_t fsize(const char *filename) {
struct stat st;

if (stat(filename, &st) == 0)
return st.st_size;

return -1;
}

int main(){
int record_size=24;
int num_records=fsize("delme.unf") / record_size;
FILE* binfile = fopen("delme.unf","rb") ;
int* record = (int*) malloc (record_size) ;
size_t result ;
for (unsigned j=0; j < num_records; j++) {
fseek(binfile, j * record_size, SEEK_SET) ;
printf("%i : ", j) ;
result=fread(record,sizeof(int),record_size/sizeof(int),binfile) ;
for (unsigned i = 0; i<result; i++){
printf("%i ",record[i]) ;
}
printf("\n");
}
free(record);
fclose(binfile);
}

输出:

0 : 1 2 3 0 0 0 
1 : 4 5 6 0 0 0

也不错。

我注意到的一些事情:

  • 您的缓冲区是char 类型——意味着每个元素一个字节。但是整数有 4 个字节。这意味着文件内容被分成几个元素。
  • 此外,您的 Fortran 代码将记录长度设置为 24(字节,我假设),但是 3 个整数每个只使用 4 个字节,因此没有使用一半的记录。这就是为什么 read 再给出三个零。
  • 如果你有 result 元素,那么 buffer 的索引需要从 0result-1.
  • 您确定文件大小的方式显然不是一个好主意,请参阅 here
  • 您正在使用 %f 作为输出,表示 float ?但我认为这些是整数?

当然,如果你不关心乱序读取数据,你可以循环遍历文件:

#include <stdlib.h>
#include <stdio.h>

int main() {
FILE* data = fopen("delme.unf", "rb") ;
int var ;
while (! feof(data )) {
fread(&var, sizeof(int), 1, data);
printf("%i ", var);
}
printf("\n");
fclose(data);
}

肯定有人会帮助您编写比我更好的 C 代码。

关于c++ - 在 C++ 中读取直接访问 Fortran 未格式化的文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30065508/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com