Fortranでファイルの読み書きRead/Writeする

Fortran入門: データ入出力
http://www.nag-j.co.jp/fortran/FI_14.html
format文 (Fortranプログラミング入門マニュアル | Fortran プログラミング 入門 講座)
http://harukin.la.coocan.jp/fortran/004/format.html

Fortranのファイル読み書き&フォーマット文に関しては上記を参照。
ただし、Fortran77 の時もそうだったのだが、Fortran で書き出して、Fortran で読み込む分にはさほど書式に気を遣わなくていい…というか、適当に write(*,*) で書き出して、read(*,*) で読み込めるってのが Fortran の便利なところ。

program Console1
    implicit none
    integer count
    integer readdata
    character*80 fname

    ! ファイル出力
    open(10,file='sample.txt',status='replace')
    write (10,*) 'Hello', x, y 
    close(10)
    print *, 'write sample.txt'

	! 一応初期化    
    x = 0 
    y = 0

    ! ファイル入力
    open(11,file='sample.txt',status='old')
    read(11,*), str, x, y
    close(11)
    
    print *, 'read sample.txt'
    print *, 'read:', str, x, y
    
    fname = 'sample2.txt'
    count = readdata(fname)
    print *,'read count:', count 
end program Console1

フォーマットを決めずに write した後に read する例。単純に、変数を並べて write すれば良しなにしてくれるので非常に便利です。固定のデータ数や配列の場合には、ちまちま書くか、do ループを使って固定数分読み書きすればよい。

    ! データを終端 "END" まで読み込む
    integer function readdata(fname)
        implicit none
        ! character*80 :: fname
        character(*), intent(in) :: fname
        integer :: count
        character*20 :: mark
        integer :: x, y
        count = 0
        
        print *,'fname:', fname
        open(10,file=fname,status='old')
        do 
            read(10,*,end=100), mark, x, y
            count = count + 1
            if ( mark == 'end' ) then
                exit
            end if
            print *, 'read:',x,y
        end do
100     close(11)        
        readdata = count
    end function readdata

この do ループの部分は定番です。read の時に end=100 のように行番号で飛ばすのは、Fortran90 のスタイルではどうなのだろう?と思うのですが、ひとまずこれで。ファイル番号を付けるのは、VB6 と同じです。適当にダブらない番号を付ければ OK です。ただし、サブルーチンからサブルーチンを呼び出すときに、このファイル番号がダブった場合どうなるのかは不明。なので、open/close 自体はちょっと注意しないと。

このサンプルでは、文字列の先頭が「end」で終わったときに終端と判断していますが、数値が「-1」の時というのも定番な動作です。C++の場合は、1行読み込んだ後に、先頭が「end」なのか、有効な数字なのかという判断をしますが、Fortranの場合は、文字列を数値を混在させるのは面倒なので、最初のカラムが数値ならば「-1」で、文字列にするならば「end」でという使い分けをしたほうが良いでしょう…と fortran90 初心者は思う訳です(fortran77は昔やったことがあるけど)。「end」を終端にする場合は、先頭のカラムの文字列は捨てカラムにするのが良いですね。

data	10	21
data	11	22
data	12	23
data	13	24
end

のように、先頭のカラムを捨ててしまうわけです。実は、これが便利なのは先頭が「data」の時はデータ行をあらわして「end」の場合は終端、という形で1行を読み込んだときに判断が付くところです。perl で処理する時に楽だったりします。大学の頃は、フォーマットの前処理を perl でやって、最終的に fortran で読み込ませる方法を取っていました。

カテゴリー: 開発, Fortran パーマリンク