简体   繁体   English

从十六进制转储将Fortran实际数据类型读取到Matlab中

[英]Reading the Fortran real data type into Matlab from a hex dump

As the title says I am writing a large amount of real arrays from Fortran into an unformatted file, and then trying to read that binary file into Matlab. 如标题所述,我正在将大量的真实数组从Fortran写入一个未格式化的文件,然后尝试将该二进制文件读入Matlab。 I have successfully made my script work for strings and integers, but It does not correctly read my real numbers from the hex dump. 我已经成功地使脚本适用于字符串和整数,但是它无法从十六进制转储中正确读取我的实数。

As a test case I was using the number 5.49. 作为测试用例,我使用数字5.49。 Interesting side note, according to an online converter that is 40 af ae 14 , yet when I check my hexfile that portion of my code is reading 14 ae af 40 . 有趣的是,根据在线转换器40 af ae 14 ,但是当我检查hexfile时,我的代码部分正在读取14 ae af 40 I have tried reading it in as a float32 and double , and I have changed fro neutral to little endian to big endian. 我尝试将其读取为float32double ,并且将中性从小尾数改为大尾数。 Any ideas? 有任何想法吗?

Here is a simple example of my code: 这是我的代码的一个简单示例:

First the Fortran write statements 首先,Fortran写语句

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

Now the Matlab read statement 现在,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);

My guess is that there is something funky with the Fortran REAL type. 我的猜测是Fortran REAL类型有些时髦。 Maybe it's not quite a floating point? 也许这不是一个浮点数?

Good job on the bit level work getting this far, you are almost there. 比特级的工作要做得很好,到此为止,您快要完成了。 "Big Endien versus little..." “大恩蒂恩与小...”

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

http://www.lahey.com/docs/lfenthelp/F95ARINQUIREStmt.htm 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://software.intel.com/zh-CN/forums/intel-fortran-compiler-for-linux-and-mac-os-x/topic/270026

There is also manually shifting it https://www.nsc.liu.se/~boein/f77to90/a5.html#section10 也可以手动移动它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

Section 1-5 to 1-9 https://data.cresis.ku.edu/data/mat_reader/matfile_format.pdf . 第1-5至1-9节https://data.cresis.ku.edu/data/mat_reader/matfile_format.pdf You may notice like I did that type15 is 'miCOMPRESSED', so at that point one needs the uncompressor to make sense of it. 您可能会像我一样注意到type15是'miCOMPRESSED',因此此时需要使用解压器来理解它。

You'll need to test it like you did before, because it is easy for me to get the order wrong, and I am doing this by memory.(Updated as I was doing this today, but in a subroutine, so it should work as a function??) 您需要像以前一样对其进行测试,因为我很容易弄错订单,而且我正在通过内存来执行此操作。(今天更新此操作,但在一个子例程中,因此它应该可以工作作为功​​能??)

I made it 4 in case you need an '8' version... And then you just call Shifty() and you can get the one that matches your data. 如果您需要一个'8'版本,我将其设置为4 ...然后您只需调用Shifty()即可获得与您的数据匹配的版本。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM