2016-11-17 15 views
0

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

В качестве тестового примера я использовал номер 5.49. Интересное примечание стороны, согласно онлайн-конвертеру, то есть 40 af ae 14, но когда я проверяю свой hexfile, что часть моего кода читает 14 ae af 40. Я пробовал читать его как float32 и double, и я изменился с нейтрального на маленького endian на большой endian. Есть идеи?

Вот простой пример моего кода:

Первая Фортран заявления записи

REAL :: floating = 5.49 
open(unit = 2, file = "anxietySource", form = "unformatted", status = "new", action = "readwrite") 
write(unit = 2) floating 

теперь Matlab прочитал заявление

fid = fopen('anxietySource', 'rb'); 
h1 = fread(fid, 1, 'int32'); %this is just reading off the starter bits that tell me how long my write statement is 
floating = fread(fid,1,'float32'); 
display(floating); 
fclose(fid); 

Я думаю, что есть что-то в стиле фанк с тип Fortran REAL. Может быть, это не совсем плавающая точка?

+0

на самом деле не обращается к центральному вопросу, но с современным fortran вы можете указать 'access = 'stream'' на open и поэтому не нужно иметь дело с данными заголовка. Попробуйте это и проверьте, что результирующий файл равен четырем байтам. – agentp

+0

для сравнения в моей маленькой системе конца байты: «14 ae af 40» и mathematica читают ее как «Real32» просто отлично. Я предполагаю, что вы понимаете, что '5.49' не является точно представимым, а фактическое значение у вас -' 5.48998..' или около того. (не знакомы с Matlab, но я полагаю, что «плавающий» 64 бит, поэтому вы увидите что-то подобное.) – agentp

ответ

0

Хорошо, что работа на уровне бит работает так далеко, вы почти там. "Большой Endien против мало ..."

https://gcc.gnu.org/onlinedocs/gfortran/CONVERT-specifier.html

http://www.lahey.com/docs/lfenthelp/F95ARINQUIREStmt.htm

https://software.intel.com/en-us/forums/intel-fortran-compiler-for-linux-and-mac-os-x/topic/270026

Там также вручную сдвигая его https://www.nsc.liu.se/~boein/f77to90/a5.html#section10

MODULE Shifty 
PRIVATE 

INTERFACE Shift 
    MODULE PROCEDURE Shift4 !,Shift8 
END INTERFACE 

CONTAINS 
REAL FUNCTION Shift4(MyFloat) 
IMPLICIT NONE 
REAL, INTENT(IN) :: MyFloat 
INTEGER*4  :: Float1 
INTEGER*4  :: Float2 
INTEGER*4  :: Float3 
INTEGER*4  :: Float4 

INTEGER*4  :: MyInt 
EQUIVALENCE(MyInt, MyFloat) 
INTEGER*4  :: MyIntOut 
EQUIVALENCE(MyIntOut, Shift4) 

WRITE(*,20) MyInt 
20 FORMAT('Incoming Real=',1PE12.5,' ==",Z8.8,'"') 

Float1 = IBITS(MyInt, 0, 8) 
Float2 = IBITS(MyInt, 8, 8) 
Float3 = IBITS(MyInt,16, 8) 
Float4 = IBITS(MyInt,24, 8) 

WRITE(*,30) 1, Float1  !Check 
WRITE(*,30) 2, Float2 
WRITE(*,30) 3, Float3 
WRITE(*,30) 4, Float4 
30 FORMAT('Float',I1,'="',Z2.2,'"') 

Float1 = ISHFT(Float1, 24) 
Float2 = ISHFT(Float2, 16) 
Float3 = ISHFT(Float3, 8) 
Float4 = ISHFT(Float4, 0) 

MyIntOut = IOR(Float1 , Float2) 
MyIntOut = IOR(MyIntOut, Float3) 
MyIntOut = IOR(MyIntOut, Float4) 

WRITE(*,20) MyInt, MyIntOut 
20 FORMAT('Incoming Real="',Z8.8,' Outgoing="',Z8.8,'"') 

RETURN 
END FUNCTION Shift4 

END MODULE Shifty 

PROGRAM MAT2F90 
USE Shifty 
IMPLICIT NONE 

TYPE MATLAB_HEADER 
    CHARACTER(LEN=120) :: Descriptor !should be 116 and INT*8 !! 
    INTEGER*4   :: Offset 
    INTEGER*2   :: Version 
    CHARACTER(LEN=2) :: Endien 
END TYPE MATLAB_HEADER 

TYPE MATLAB_SUBHEADER 
    INTEGER*4   :: Type 
    INTEGER*4   :: Bytes 
END TYPE MATLAB_SUB_HEADER 

TYPE(MATLAB_HEADER)     :: Head 
TYPE(MATLAB_SUB_HEADER),DIMENSION(20) :: Tag 
CHARACTER(LEN=12), DIMENSION(18) :: Matlab_Version = RESHAPE(& 
['miINT8  ','miUINT8  ','miINT16  ','miUINT16 ', & 
'miINT32  ','miUINT32 ','miSINGLE ','Reserved ', & 
'miDOUBLE ','Reserved ','Reserved ','miINT64  ', & 
'miUINT64 ','miMATRIX ','miCOMPRESSED','miUTF8  ', & 
'miUTF16  ','miUTF32  '],[18]) 
LOGICAL :: Swap 
... 
OPEN(UNIT=22,FILE='<somename>',ACCESS='STREAM',FORM='UNFORMATTED',IOSTAT=Status) 
IF(Status =/0) ...Do something 

READ(20,IOSTAT=Status) Head 
IF(Status =/0) ...Do something 

WRITE(*,*)'Head.Descriptor="',Head.Descriptor,'"' 
WRITE(*,*)'Head.Offset = ',Head.Offset 
WRITE(*,*)'Head.Version = ',Head.Version 
WRITE(*,*)'Head.Endien ="',Head.Endian,'"' 
IF(Head.Endian == 'IM') THEN 
    SWAP = .FALSE. 
ELSEIF(Head.Endian == 'MI') THEN 
    SWAP = .TRUE. 
ELSE 
    WRITE(*,*)'Unknown Endien="',Head.Endian,'"' 
    STOP 
ENDIF 

READ(20,IOSTAT=Status) Tag(1) 
IF(Status =/0) ...Do something 
WRITE(*,*)'Tag(1).Type = ',Tag(1).Type,' == "',Matlab_Version(Tag(1).Type),'"' 
WRITE(*,*)'Tag(1).Bytes= ',Tag(1).Bytes 
!read and swap if need be... 
!There is padding to an 8type boundary 
!Read the next tag and data... etc 

Раздел 1-5 к 1 -9 https://data.cresis.ku.edu/data/mat_reader/matfile_format.pdf. Вы можете заметить, что я сделал этот тип15 - это «miCOMPRESSED», поэтому в этот момент нужен декомпрессор, чтобы понять это.

Вам нужно будет протестировать его так, как вы делали это раньше, потому что мне легко получить неправильный порядок, и я делаю это по памяти. (Обновлен, как я делал это сегодня, но в подпрограмме , поэтому он должен работать как функция?)

Я сделал это 4, если вам нужна версия «8» ... И тогда вы просто вызываете Shifty(), и вы можете получить тот, который соответствует вашим данным.

+0

Спасибо! Я пробовал читать его как как большой, так и маленький endian, но я еще не пытался писать его как особый тип. Возможно, если я явно напишу его как один или другой, он исправит мою проблему. Я дам вам знать ! – Chair

+0

К сожалению, это не решило проблему. – Chair

+0

Если это проблема с endian, может быть предпочтительнее исправить ее на стороне matlab (с одной стороны, исправления fortran не являются стандартными).'fread' принимает простой аргумент для выполнения байтового обмена. – agentp

 Смежные вопросы

  • Нет связанных вопросов^_^