2011-08-02 52 views
2

數組這是一定的相關性我最近交的Fortran流和類似:Converting data stored in Fortran 90 binaries to human readable format使用的Fortran流正確地寫入和讀取整數

我正在嘗試將一個整數的簡單數組寫入文件,然後使用Fortran的READ函數讀取我創建的二進制文件。我通過在我的OPEN指令中包含ACCESS="STREAM"來使用流。我有以下代碼:

MODULE streamtest2subs 

    IMPLICIT NONE 

CONTAINS 

SUBROUTINE writeUstream(myarray) 
    IMPLICIT NONE 
    INTEGER, INTENT(IN), DIMENSION(4,10) :: myarray 
    INTEGER :: myvalue = 12345, mypos 
    OPEN(UNIT=11, FILE="ustream.demo", STATUS="REPLACE", ACCESS="STREAM") 
    WRITE(11) myarray 
    CLOSE(UNIT=11) 
END SUBROUTINE writeUstream 

SUBROUTINE readUstream 
    IMPLICIT NONE 
    INTEGER :: test1, test2, test3 
    INTEGER :: n 
    OPEN(UNIT=42, FILE="ustream.demo", STATUS="OLD", ACCESS="STREAM") 
    READ(42, POS=1) test1 
    READ(42, POS=2) test2 
    READ(42, POS=3) test3 

    WRITE(*,*) "This is the output:" 
    WRITE(*,*) test1 
    WRITE(*,*) test2 
    WRITE(*,*) test3 
END SUBROUTINE readUstream 

END MODULE streamtest2subs 

PROGRAM streamtest2 
    USE streamtest2subs 
    IMPLICIT NONE 
    INTEGER :: i, j, k 
    INTEGER, DIMENSION(4,10) :: a 

    WRITE(*,*) "This is my input array:" 
    k=1 
    DO i=1,4 
    DO j=1,10 
     a(i,j)=k 
     WRITE(*, "(i3)", ADVANCE="NO") a(i,j) 
     k=k+1 
    END DO 
    WRITE(*,*) 
    END DO 
    WRITE(*,*) 

    CALL writeUstream(a) 
    CALL readUstream 
END PROGRAM streamtest2 

然而,當我編譯這個使用gfortran並運行它,我得到以下的輸出:

This is my input array: 
    1 2 3 4 5 6 7 8 9 10 
11 12 13 14 15 16 17 18 19 20 
21 22 23 24 25 26 27 28 29 30 
31 32 33 34 35 36 37 38 39 40 

This is the output: 
      1 
    184549376 
     720896 

爲什麼是它的輸出是如此複雜?難道READ是閱讀ustream.demo文件作爲一個字符串,而不是作爲一個整數?但是,當我將test1,test2和test3的類型更改爲字符串時,我的輸出只是一系列三個空行。

我使用的POS指令在READ不正確?我認爲POS指定了輸出中的字符數(儘管我不確定數組中的元素是否以任何方式分隔)。它是否正確?

非常感謝您的時間!

回答

5

對於你以前的問題所描述的目的,我認爲你是編程這個複雜得多,是必要的。假設你想要一個沒有額外記錄結構的二進制文件,你需要非格式化和流。您可以使用與編寫文件相同的方式閱讀文件 - 您不需要使用POS - 除非目的是學習如何使用POS。

我測試的例子是基於一個Fortran程序,在該程序中我讀取了一個由別人編寫的二進制文件,幾乎可以肯定是用C程序編寫的。該文件由標題組成,隨後是可變長度的數組。我打開文件:

open (unit=75, file=FileName, status='old', access='stream', form='unformatted', action='read') 

我讀一個頭(一個變量,它是用許多子變量用戶定義型):

read (75) header 

我分配數組的長度被讀然後我讀數組:

allocate (array (1:header % ArrayLen)) 
read (75) array 

然後我處理數組中的數據。 然後我重複,直到文件結束(代碼示例中未顯示)。

很簡單...不需要計算文件中的位置並使用READ的POS關鍵字。

+0

謝謝! – Andrew

3

問題是您的讀取語句,POS是從文件開始的字節偏移量,並且與寫入文件的原始a數組的索引沒有直接關係。

所以,在你的代碼,如果test1是一個4字節整數Fortran語言讀將讀取字節1到文件的4構造它。類似地,test2將從字節2被構造成如圖5所示,而值實際存儲在字節5到8

當我改變所讀取的行,

READ(42, POS=1) test1 
READ(42, POS=5) test2 
READ(42, POS=9) test3 

輸出成爲,

This is my input array: 
1 2 3 4 5 6 7 8 9 10 
11 12 13 14 15 16 17 18 19 20 
21 22 23 24 25 26 27 28 29 30 
31 32 33 34 35 36 37 38 39 40 

This is the output: 
     1 
     11 
     21 

我認爲這是更你是什麼之後。請注意,如果值寫入文件最初作爲,比方說,2字節或8字節的整數,那麼你將有當您閱讀該文件以解釋在POS偏移的大小。

順便說一句,值得學習命令行工具od以快速查詢二進制文件。例如,我做的第一件事是檢查寫入工作還好用,

$ od -t d4 ustream.demo 
0000000     1    11    21    31 
0000020     2    12    22    32 
0000040     3    13    23    33 
0000060     4    14    24    34 
0000100     5    15    25    35 
0000120     6    16    26    36 
0000140     7    17    27    37 
0000160     8    18    28    38 
0000200     9    19    29    39 
0000220    10    20    30    40 
0000240 
+0

非常感謝! – Andrew

+0

感謝您展示如何使用'od'! – EMiller