在Fortran中读取流二进制文件

时间:2018-06-29 10:41:41

标签: binary fortran gfortran

我正在读取一个二进制文件,在其中我知道一个大向量的字节位置,该向量包含以IBM格式(描述为here的4字节实数写的10 ^ 8个数据样本)。

据我所知,Fortran中的实数类型使用更新的IEEE样本格式(符号为1位,指数为8位而不是IBM格式为7位),如here所述。因此,如果假设采用实数格式读取这些实数值,则会给我错误的值,因此我想将每个实数分成4个整数,每个整数占一个字节,然后进行转换以从4个整数字节中获取IEEE样本数据。

我编写了以下测试程序来研究此问题,在该程序中,我分别在字节位置1和5中声明了一个正实数 a1 = 1876752.76854 和它的负当量 a2 = -a1 (a1和a2声明为4个字节长(种类= 1))。

稍后,我从流文件中读取了相同类型b1和b2的两个实数的相同字节位置,但是我还在相同字节位置中读取了两个整数n1和n2(每个4个字节),以查看是否可以获取从整数类型轻松实现IEEE实类型。我还读取了4个整数(每个1个字节)以使用它们计算IEEE值,如下所示:

program test_real_types
implicit none
integer,parameter       :: rk=kind(1.0)
real(rk)         :: a1,a2,b1,b2
integer(kind=1)  :: bytes1(4),bytes2(4)
integer          :: i
integer(kind=4)  :: n1,n2

a1=1876752.76854
a2=-a1

open(1,file='reals.dat',access="stream",form="unformatted")

write(1,pos=1) a1
write(1,pos=5) a2
close(1)

open(2,file='reals.dat',access="stream",form="unformatted",status="old")

!! reading byte positions: 1-4
do i=1,4
read(2,pos=i) bytes1(i)
enddo
read(2,pos=1) n1  !! read integer n1 of 4 bytes length in the same position
read(2,pos=1) b1  !! read real (4 bytes) in the same position

!! reading byte positions: 5-8
do i=5,8
read(2,pos=i) bytes2(i)
enddo
read(2,pos=5) n2
read(2,pos=5) b2

write(*,*) 'bytes1 = ',bytes1(1:4)
write(*,*) '    n1 = ',n1
write(*,*) '    b1 = ',b1
write(*,*) 'bytes2 = ',bytes2(1:4)
write(*,*) '    n2 = ',n2
write(*,*) '    b2 = ',b2
end program test_real_types

执行上面的代码后,我得到了以下信息:

 bytes1 =   -122   24   -27   73
     n1 =   1239750790
     b1 =    1876752.8
 bytes2 =      0    0     0    0
     n2 =   -907732858
     b2 =   -1876752.8

结果表明,n2不等于-n1(预期值),但令我惊讶的是,当逐字节读取字节5-8时,它们正确地将b2打印为-b1时,字节5-8都等于零。我试图读取字节9,但是按预期它是空的。

在我可以正确读取a2和非零整数n2的实际值的同时,如何获得5-8位置的零字节的任何帮助吗?

1 个答案:

答案 0 :(得分:3)

首先,您的程序存在错误:

% gfortran -O2 -g -Wall -fcheck=all test_real_types.f90 
% ./a.out 
At line 30 of file test_real_types.f90
Fortran runtime error: Index '5' of dimension 1 of array 'bytes2' above upper bound of 4

修复了明显的错误,并避免使用<10的单位号(通常,这是一个好主意,尽管本质上与您在此处看到的错误无关),我得到了

% ./a.out      
 bytes1 =  -122   24  -27   73
     n1 =   1239750790
     b1 =    1876752.75    
 bytes2 =  -122   24  -27  -55
     n2 =   -907732858
     b2 =   -1876752.75