2011-08-02 18 views
2

これは、Fortranストリームなどについての私の最近の投稿と多少関連しています:Converting data stored in Fortran 90 binaries to human readable formatFortranストリームを正しく使用して整数の配列を読み込んで読み込みます

単純な整数の配列をファイルに書き込もうとしていますが、次にFortranのREAD関数を使用して、作成したバイナリを読み込みます。私はOPENの指示にACCESS="STREAM"を含めてストリームを使用しています。私は、次のコードを持っている:私はこの使用のgfortranをコンパイルし、それを実行したときに

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 

をしかし、私は次のような出力が得られます。

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 

なぜそれが、出力が非常に複雑であるということですか? READustream.demoファイルを整数ではなく文字列として読み込んでいますか?しかし、test1、test2、およびtest3のタイプをstringに変更すると、私の出力は単に一連の3つの空白行に過ぎません。

READPOS指令を間違って使用していますか?私はPOSが出力の文字数を指定していると思いますが(配列の要素がどのように区切られているかわかりませんが);これは正しいです?

ありがとうございます!

答えて

5

を確認しました、私はあなたが必要であるよりも、このより複雑なプログラミングをしていると思います。余分なレコード構造を持たないバイナリファイルが必要な場合は、フォーマットされていないストリームが必要です。 POSを使用する方法を学ぶことを目的としない限り、書いたのと同じ方法でファイルを読むことができます - あなたはPOSを使う必要はありません。

私がテストした例は、他の誰かによって書かれたバイナリファイルを、ほぼ確実にCプログラムで読むFortranプログラムに基づいています。ファイルはヘッダーで構成され、可変長の配列が続きます。私が読み取られた長さの配列を割り当てる

read (75) header 

:私はヘッダを読み取る

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

(ユーザ定義多くのサブ変数を持つタイプである変数):私は、ファイルを開きますヘッダーの1つのフィールドに入力すると、配列が読み取られます。

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

次に、配列のデータを処理します。 その後、ファイルの最後まで繰り返します(コードサンプルには表示されません)。

ファイル内の位置を計算する必要はなく、READのPOSキーワードを使用する必要はありません。

+0

ありがとうございます! – Andrew

3

問題はあなたのreadステートメントで、POSはファイルの先頭からのバイトオフセットであり、ファイルに書き込まれた元のa配列の配列インデックスには直接関係しません。

したがって、test1が4バイトの整数の場合、Fortranの読み取りは、ファイルのバイト1〜4を読み取ることによってそれを構築します。私がリード線を変更すると値が実際に8

のバイト5に格納されているのに対し同様、test2は、5のバイト2から構成されることになる

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

関連する問題