2016-11-17 92 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