2016-11-17 87 views
0

正如标题所示,我正在将大量来自Fortran的真实数组写入未格式化的文件,然后尝试将该二进制文件读入Matlab。我已经成功地使我的脚本适用于字符串和整数,但它不能正确读取我的实数从十六进制转储。通过十六进制转储将Fortran真实数据类型转换为Matlab

作为一个测试用例,我使用的是数字5.49。有趣的一面是,根据一个在线转换器,它是40 af ae 14,但当我检查我的hexfile时,我的代码部分是14 ae af 40。我曾尝试将它作为float32double阅读,我已经从中性变为小端到大端。有任何想法吗?

这里是我的代码一个简单的例子:

首先,Fortran语言写的语句

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'',因此不需要处理标题数据。尝试一下,并验证生成的文件恰好是四个字节。 – agentp

+0

作为比较,我的小端系统的字节是'14 ae af 40',而数学公司将它读作“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

谢谢!我曾尝试将它作为大小写字母读取,但我还没有试图将其作为特定类型编写。也许如果我明确地将它写入一个或另一个,它将解决我的问题。我会让你知道的 ! – Chair

+0

不幸的是,这并没有解决问题 – Chair

+0

如果它是一个endian问题它可能会更好地修复它在matlab方面(一方面fortran修复不是标准的)。'fread'采用一个简单的参数来进行字节交换。 – agentp