Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Io 读取未格式化的二进制文件:意外输出-Fortran90_Io_Fortran_Binaryfiles_Fortran90 - Fatal编程技术网

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

Io 读取未格式化的二进制文件:意外输出-Fortran90,io,fortran,binaryfiles,fortran90,Io,Fortran,Binaryfiles,Fortran90,前言:我需要弄清楚二进制网格数据文件的结构。根据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) 现在,为了进行测试,我编写了一个简单的程序,如下所示:(我没

前言:我需要弄清楚二进制网格数据文件的结构。根据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)
现在,为了进行测试,我编写了一个简单的程序,如下所示:(我没有包括所有的参数)

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

  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(或其他任何地方)背景的记录。请参阅英特尔提供的以下文档,其中对不同的访问模式进行了很好的解释:

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

此外,我不能使用ACCESS=stream,因为机器很旧而且不受支持,所以我得出结论,以上是确定文件结构的唯一可能性。任何指导都会大有帮助

如果您不能使用
,那么实际上没有简单、轻松的方法来读取没有记录信息的二进制文件

需要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
改为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);
}
使用
/write
创建二进制文件,然后查看Fortran代码如何使用
/readbin
读回该文件

这可以扩展到不同的数据类型,以基本模拟
access=stream
。最后,如果您可以重新编译原始Fortran代码,以不同的方式输出数据文件,这将是最简单的解决方案,因为这是一个非常粗糙的破解

最后,一个进入未知数据格式的技巧:工具
od
是您的朋友,请查看其手册页。它可以直接将二进制表示转换为各种不同的本机数据类型。尝试上面的示例(z在右侧列中添加字符表示,在这里不是很有用,通常是):


不应直接输入直接访问的记录长度,如
200
。处理器不必使用字节作为长度单位,应该使用
inquire
语句来获取它。另外,当你之前声明的是
57
字节时,为什么要使用
200
?顺便说一句,没有哪个mod或admin进行向下投票,这是所有用户之间的反馈。当你获得足够的声誉时,你还可以投票选择其他问题和答案。还有,不要因为一张否决票而生气,那是会发生的。试着找出什么能激发它。许多用户害怕告诉你他们为什么投票否决了这篇文章,因为有些用户对他们进行了报复。弗拉基米尔,你说得对极了。我一开始就是这么做的。在open语句之前,我在open语句之前使用了
INQUIRE(file=filename,recl=irec)
,但它给了我一个错误。RECL说明符为零或为负。所以,在向下投票时,我没有感到愤怒或任何事情。这是令人沮丧的。不管怎么说,我觉得自己像个傻瓜,然后对你的问题投了反对票,这只会增强我的傻瓜感!此外,如果没有记录,你甚至没有机会提高,也不能保证OP将来不会再犯同样的错误!你知道,这是一个恶性循环!您无法从文件中获取长度,必须从记录
INQUIRE(iolength=irec)x、y、z、lat_gap、lon_gap、north_lat、west_lat、nclat、nclon、gridtyp
中写入的变量中获取长度。谢谢Markus,我将在下周尝试。我刚看到你的反应。关于第二个问题(补充问题)。在我的搜索过程中,我遇到了hextump选项(您已经提到了od)。如果我使用hextump转换工具来读取文件,有意义吗?我还发现MATLAB可以读取这样的文件。
#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);
}
#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
od -t fDz test.bin