我有一个包含斜率和截距的.bin文件。我正在使用Fortran来读取值,并且我在运行AIX和Linux的机器上获得了不同的值。我相信Linux数据是准确的。这是否与堆栈大小或字节序有关?
例如,AIX最大值为:0.3401589687E + 39,而Linux最大值为:6.031288
program read_bin_files
REAL :: slope(2500,1250)
INTEGER :: recl=2500*1250*4
OPEN(UNIT=8, FILE='MODIS_AVHRR_years_slope.bin', ACTION='READ', ACCESS='direct', FORM='unformatted', RECL=recl, IOSTAT=iostat)
READ(unit=8, REC = 1, IOSTAT = iostat) slope
print *, "Max slope value is:", maxval(slope)
CLOSE(8)
end
答案 0 :(得分:1)
AIX运行(现在)在POWER CPU上运行,这些通常是 big-endian,而Linux 通常在x86es上运行,它们是little-endian。所以你怀疑字节序可能是一个问题是正确的。您报告运行此程序
的结果program read_bin_files
INTEGER*4 :: slope(2500,1250)
INTEGER :: recl=2500*1250*4
OPEN(UNIT=8, FILE='MODIS_AVHRR_years_slope.bin', ACTION='READ', &
ACCESS='direct', FORM='unformatted', RECL=recl)
READ(unit=8, REC = 1) slope
DO i = 1, 10
WRITE(*, '(Z8.8)') slope(1, i)
END DO
CLOSE(8)
end
如下。 (" AIX"和#34; Linux"在列标题中都有引号,因为它是 CPU 在这里很重要,而不是操作系统。)
"Linux" | "AIX"
------------+------------
3E C2 61 8F | 8F 61 C2 3E
3E F5 64 52 | 52 64 F5 3E
BC F3 E0 7E | 7E E0 F3 BC
BF B9 71 0D | 0D 71 B9 BF
3E F5 B9 73 | 73 B9 F5 3E
3F 29 3C 2F | 2F 3C 29 3F
3E DC C2 09 | 09 C2 DC 3E
3F 66 86 89 | 89 86 66 3F
3E 5B 91 A9 | A9 91 5B 3E
3F 67 73 25 | 25 73 67 3F
在每一行中,右半部分是左半部分的镜像。这表明问题是字节序。我们还不知道哪个字节顺序正确。该问题的答案几乎肯定是"运行生成文件的程序的CPU使用的字节顺序。"
如果您使用的是GNU Fortran,the CONVERT specifier to OPEN应该可以解决问题,前提是您可以找出应该解释数据的方式。但是,我认为是一个扩展。在一般情况下,我不太了解FORTRAN告诉你该怎么做。
如果您可以控制生成这些数据文件的过程,则可以通过将双方切换为自我描述的数据格式(例如HDF)来避免整个问题。
答案 1 :(得分:1)
您的AIX机器可能是大端RISC,您的Linux可能是PC或其他Intel平台。只需转换字节序。
我将这些过程用于4字节和8字节变量(在模块中使用iso_fortran_env
):
elemental function SwapB32(x) result(res)
real(real32) :: res
real(real32),intent(in) :: x
character(4) :: bytes
integer(int32) :: t
real(real32) :: rbytes, rt
equivalence (rbytes, bytes)
equivalence (t, rt)
rbytes = x
t = ichar(bytes(4:4),int32)
t = ior( ishftc(ichar(bytes(3:3),int32),8), t )
t = ior( ishftc(ichar(bytes(2:2),int32),16), t )
t = ior( ishftc(ichar(bytes(1:1),int32),24), t )
res = rt
end function
elemental function SwapB64(x) result(res)
real(real64) :: res
real(real64),intent(in) :: x
character(8) :: bytes
integer(int64) :: t
real(real64) :: rbytes, rt
equivalence (rbytes, bytes)
equivalence (t, rt)
rbytes = x
t = ichar(bytes(8:8),int64)
t = ior( ishftc(ichar(bytes(7:7),int64),8), t )
t = ior( ishftc(ichar(bytes(6:6),int64),16), t )
t = ior( ishftc(ichar(bytes(5:5),int64),24), t )
t = ior( ishftc(ichar(bytes(4:4),int64),32), t )
t = ior( ishftc(ichar(bytes(3:3),int64),40), t )
t = ior( ishftc(ichar(bytes(2:2),int64),48), t )
t = ior( ishftc(ichar(bytes(1:1),int64),56), t )
res = rt
end function
用法:
SLOPE = SwapB32(SLOPE)
还有其他方法。有些编译器支持非标准OPEN(...,CONVERT='big_endian',...
,有些编译器有-fconvert=big-endian
等命令行选项。
答案 2 :(得分:0)
元素函数SwapB64很优雅,很适合这些问题。 要么 尝试使用big_endian,little endian等。 (我个人也愿意)
!OPEN(UNIT=8, FILE='MODIS_AVHRR_years_slope.bin', ACTION='READ', ACCESS='direct', FORM='unformatted', RECL=recl, IOSTAT=iostat)
OPEN(UNIT=8, FILE='MODIS_AVHRR_years_slope.bin', CONVERT='big_endian', ACTION='READ', ACCESS='direct', FORM='unformatted', RECL=recl, IOSTAT=iostat)