Fortran 90 中的二进制文件数据读取不正确
Binary file data reading incorrectly in Fortran 90
我正在读取用不同程序编写的二进制文件。 open & read 语句似乎成功了,我在之前的 post 中得到了帮助。但是,读入的数据与文件不匹配。我已经初始化了二维数组,但在读取文件后,该数组不包含数据,但看起来是一个未初始化的数组。我已经 post 编辑了下面的代码来读取和打印数组。有什么想法吗?
allocate(dummy(imax,jmax))
dummy = 0.0
open(unit=io, file=trim(input), access='direct', iostat=ioer, &
status='old', action='READ', recl=imax*jmax*4)
if(ioer/=0) then
print*, 'Cannot open file'
else
print*,'success opening file'
end if
j=0
k=0
read(unit=io,rec=1,iostat=ioer) dummy!(j,k)
if(ioer/=0) then
print*, 'Cannot open file'
else
print*,'success opening file'
end if
size: do j=1, imax
do k=1, jmax
if(dummy(j,k) > 0.) print*,'i-',j,'j-',k,'frp-',dummy(j,k)
end do
end do size
print*,'j-',j,'k-',k
原文如下:
out_file = trim(output_dir)//'SEVIRI_FRP_.08deg_'//trim(season)//'.bin'
print*, out_file
print*, i_max,' i_max,',j_max,' j_max'
open (io, file = out_file, access = 'direct', status = 'replace', recl = i_max*j_max*4)
write(io, rec = 1) sev_frp
write(io, rec = 2) count_sev_frp
write(io, rec = 3) sum_sev_frp
这是打印出来的部分内容:
i- 600 j- 213 frp- 4.1759680E-08
i- 600 j- 220 frp- 8.8314310E-18
i- 600 j- 221 frp- 2.7975964E-36
i- 600 j- 246 frp- 461506.1
i- 600 j- 254 frp- 19.79016
i- 600 j- 255 frp- 2.0032716E-22
i- 600 j- 260 frp- 1.0871451E+24
j- 601 k- 401
这与应有的部分相同:
i- 600 j- 213 frp- 13.6999998
i- 600 j- 218 frp- 63.2000008
i- 600 j- 220 frp- 29.1416683
i- 600 j- 221 frp- 31.8032303
i- 600 j- 229 frp- 39.5000000
i- 600 j- 232 frp- 55.4714279
i- 600 j- 246 frp- 54.2200012
i- 600 j- 254 frp- 13.1636362
i- 600 j- 255 frp- 10.9028578
i- 600 j- 258 frp- 24.6888885
i- 600 j- 259 frp- 13.5619040
i- 600 j- 260 frp- 11.4000006
n- 601 m- 401
declaration/allocation 语句:
real, allocatable, dimension(:,:) :: dummy
allocate(dummy(imax,jmax))
dummy = 0.0
write/read & imax
is 600 jmax
is 400
这些是一样的
因为 M.S.B suggests in a comment, this is an endianess 写入文件的机器和读取文件的机器之间存在问题。
要了解这一点,请查看同一数组索引处这些值的差异:
i- 600 j- 213 frp- 4.1759680E-08
i- 600 j- 213 frp- 13.6999998
如果第一个值4.1759680E-08
是little endian,它的十六进制表示是33 33 5B 41
。当在大端机器上读取这个精确表示时,它读作 13.6999998
。如果第一个值是大端,第二个是小端,问题是一样的,除了十六进制表示是 41 5B 33 33
而不是。要解决此问题,您需要确定写入文件的机器的字节顺序。
gfortran 和 Intel Fortran(以及可能的其他语言)都提供扩展,允许您指定未格式化输入文件的字节顺序。如果写入文件的机器是big endian,在读取时将此添加到您的open
语句中:
convert='big_endian'
如果写入文件的机器是little endian,读取时在open
语句中加入:
convert='little_endian'
你表示你是在小端机器上写的,所以为了在大端机器上阅读这个,打开它:
open(unit=io, file=trim(input), access='direct', iostat=ioer, &
status='old', action='READ', recl=imax*jmax*4, &
convert='little_endian')
并且您的读取应该可以正常工作。
我正在读取用不同程序编写的二进制文件。 open & read 语句似乎成功了,我在之前的 post 中得到了帮助。但是,读入的数据与文件不匹配。我已经初始化了二维数组,但在读取文件后,该数组不包含数据,但看起来是一个未初始化的数组。我已经 post 编辑了下面的代码来读取和打印数组。有什么想法吗?
allocate(dummy(imax,jmax))
dummy = 0.0
open(unit=io, file=trim(input), access='direct', iostat=ioer, &
status='old', action='READ', recl=imax*jmax*4)
if(ioer/=0) then
print*, 'Cannot open file'
else
print*,'success opening file'
end if
j=0
k=0
read(unit=io,rec=1,iostat=ioer) dummy!(j,k)
if(ioer/=0) then
print*, 'Cannot open file'
else
print*,'success opening file'
end if
size: do j=1, imax
do k=1, jmax
if(dummy(j,k) > 0.) print*,'i-',j,'j-',k,'frp-',dummy(j,k)
end do
end do size
print*,'j-',j,'k-',k
原文如下:
out_file = trim(output_dir)//'SEVIRI_FRP_.08deg_'//trim(season)//'.bin'
print*, out_file
print*, i_max,' i_max,',j_max,' j_max'
open (io, file = out_file, access = 'direct', status = 'replace', recl = i_max*j_max*4)
write(io, rec = 1) sev_frp
write(io, rec = 2) count_sev_frp
write(io, rec = 3) sum_sev_frp
这是打印出来的部分内容:
i- 600 j- 213 frp- 4.1759680E-08
i- 600 j- 220 frp- 8.8314310E-18
i- 600 j- 221 frp- 2.7975964E-36
i- 600 j- 246 frp- 461506.1
i- 600 j- 254 frp- 19.79016
i- 600 j- 255 frp- 2.0032716E-22
i- 600 j- 260 frp- 1.0871451E+24
j- 601 k- 401
这与应有的部分相同:
i- 600 j- 213 frp- 13.6999998
i- 600 j- 218 frp- 63.2000008
i- 600 j- 220 frp- 29.1416683
i- 600 j- 221 frp- 31.8032303
i- 600 j- 229 frp- 39.5000000
i- 600 j- 232 frp- 55.4714279
i- 600 j- 246 frp- 54.2200012
i- 600 j- 254 frp- 13.1636362
i- 600 j- 255 frp- 10.9028578
i- 600 j- 258 frp- 24.6888885
i- 600 j- 259 frp- 13.5619040
i- 600 j- 260 frp- 11.4000006
n- 601 m- 401
declaration/allocation 语句:
real, allocatable, dimension(:,:) :: dummy
allocate(dummy(imax,jmax))
dummy = 0.0
write/read & imax
is 600 jmax
is 400
因为 M.S.B suggests in a comment, this is an endianess 写入文件的机器和读取文件的机器之间存在问题。
要了解这一点,请查看同一数组索引处这些值的差异:
i- 600 j- 213 frp- 4.1759680E-08
i- 600 j- 213 frp- 13.6999998
如果第一个值4.1759680E-08
是little endian,它的十六进制表示是33 33 5B 41
。当在大端机器上读取这个精确表示时,它读作 13.6999998
。如果第一个值是大端,第二个是小端,问题是一样的,除了十六进制表示是 41 5B 33 33
而不是。要解决此问题,您需要确定写入文件的机器的字节顺序。
gfortran 和 Intel Fortran(以及可能的其他语言)都提供扩展,允许您指定未格式化输入文件的字节顺序。如果写入文件的机器是big endian,在读取时将此添加到您的open
语句中:
convert='big_endian'
如果写入文件的机器是little endian,读取时在open
语句中加入:
convert='little_endian'
你表示你是在小端机器上写的,所以为了在大端机器上阅读这个,打开它:
open(unit=io, file=trim(input), access='direct', iostat=ioer, &
status='old', action='READ', recl=imax*jmax*4, &
convert='little_endian')
并且您的读取应该可以正常工作。