Bin 数据在 AIX 中的读取方式与 Linux 不同
Bin data read differently in AIX vs Linux
我有一个包含斜率和截距的 .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
AIX 运行s(这些天)在 POWER CPUs 上,通常是 big-endian,而 Linux在 x86es 上通常是 运行,这是 little-endian。所以你怀疑字节顺序可能是一个问题是正确的。您报告 运行ning this program
的结果
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" 和 "Linux" 在 headers 列中用引号括起来,因为这里重要的是 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
在每一行中,right-hand 一半是 left-hand 一半的镜像。这表明问题 是 字节顺序。我们仍然不知道哪种字节顺序是正确的。这个问题的答案几乎肯定是 "the byte order used by the CPU that ran the program that generated the file."
如果您使用的是 GNU Fortran,the CONVERT specifier to OPEN 应该可以解决问题,前提是您可以弄清楚应该以哪种方式解释数据。但是,我 认为 这是一个扩展。在一般情况下,我对 FORTRAN 的了解还不够多,无法告诉您该怎么做。
如果您可以控制生成这些数据文件的过程,则可以通过将双方切换为 self-describing 数据格式来避免将来出现整个问题,例如 HDF.
您的 AIX 机器可能是 big-endian 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
.
基本函数 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)
我有一个包含斜率和截距的 .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
AIX 运行s(这些天)在 POWER CPUs 上,通常是 big-endian,而 Linux在 x86es 上通常是 运行,这是 little-endian。所以你怀疑字节顺序可能是一个问题是正确的。您报告 运行ning this program
的结果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" 和 "Linux" 在 headers 列中用引号括起来,因为这里重要的是 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
在每一行中,right-hand 一半是 left-hand 一半的镜像。这表明问题 是 字节顺序。我们仍然不知道哪种字节顺序是正确的。这个问题的答案几乎肯定是 "the byte order used by the CPU that ran the program that generated the file."
如果您使用的是 GNU Fortran,the CONVERT specifier to OPEN 应该可以解决问题,前提是您可以弄清楚应该以哪种方式解释数据。但是,我 认为 这是一个扩展。在一般情况下,我对 FORTRAN 的了解还不够多,无法告诉您该怎么做。
如果您可以控制生成这些数据文件的过程,则可以通过将双方切换为 self-describing 数据格式来避免将来出现整个问题,例如 HDF.
您的 AIX 机器可能是 big-endian 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
.
基本函数 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)