2016-07-25 12 views
1

У меня есть .bin-файл, содержащий склоны и перехваты. Я использую Fortran для чтения значений, и я получаю разные значения на машинах с AIX и Linux. Я считаю данные Linux точными. Связано ли это с размером стека или с концами?Данные бина читаются по-разному в AIX vs 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

Почему бы не использовать 'stream' пункт доступа и избежать' recl' все вместе? У вас есть доступ к современному компилятору Fortran (2008+)? Если это так, используйте спецификатор 'newunit'. – jlokimlin

ответ

1

AIX работает (в эти дни) на СИЛОВЫХ процессоров, которые обычно большой обратный порядок байт, в то время как Linux обычно работает на x86es, которые являются малорисковыми. Поэтому вы правы, чтобы подозревать, что проблема может быть проблемой. Вы сообщаете, что результат работы этой программы

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» в кавычки в заголовках столбцов, потому что это 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 

В каждом ряду, правая половина является зеркальным образ левой половины. Это свидетельствует о том, что вопрос is endianness. Мы еще не знаем, какой порядок байтов правильный. Ответ на этот вопрос почти наверняка будет «порядком байтов, используемым процессором, который запускал программу, которая сгенерировала файл».

Если вы используете GNU Fortran, the CONVERT specifier to OPEN должен решить эту проблему, если вы можете выяснить, какой путь вокруг данных предполагается интерпретировать. Однако, я думаю это расширение. В общем случае я не знаю, достаточно ли FORTRAN, чтобы рассказать вам, что делать.

Если у вас есть контроль над процессом, генерирующим эти файлы данных, вы можете избежать всей проблемы в будущем, переключив обе стороны в самоописывающийся формат данных, например HDF.

+0

В Linux первые 10 значений: 3EC2618F, 3EF56452, BCF3E07E, BFB9710D, 3EF5B973, 3F293C2F, 3EDCC209,3F668689, 3E5B91A9, 3F677325. В AIX первые 10 действительно разные: 8F61C23E, 5264F53E, 7EE0F3BC, 0D71B9BF, 73B9F53E, 2F3C293F 09C2DC3E, 8986663F, A9915B3E, 2573673F – kkd92

+0

Спасибо. Да, это проблема эндиантности. См. Отредактированный ответ. – zwol

+0

Спасибо! Хотел подтвердить эту проблему, и вы помогли сделать это. – kkd92

1

Ваша машина AIX, скорее всего, является биллиантовым RISC, а ваш Linux, скорее всего, является ПК или другой платформой 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.

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) 
+0

Я действительно упомянул об этом. Проблема заключается в том, что этот спецификатор полностью выходит за рамки стандарта. Это не против вашего ответа, но я думаю, что это нужно упомянуть. –