6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Fortran ファイル入力での行読み飛ばし

Last updated at Posted at 2020-09-07

シーケンシャル・ファイルからデータを読み込む時、不要な行を読み飛ばすのには、空の READ 文で十分です。(かつそのほうが速いはずです)

ファイル入力読み飛ばし

Fortran のプログラム質問サイトなどを見ていますと、ファイルからデータを読み込む時、不要な行を読み飛ばすのにダミー変数への入力などをしている例が多く見受けられます。しかし、実は読み込み変数を何も書かない空っぽの READ 文だけで次の行に飛んでくれます。

書式付きの場合は、ダミー読み込みのための書式変換が要らず改行を探すだけになるため負荷が軽くなります。

書式なしの場合は(普通は)行頭と行末にレコード長が埋め込まれているので次の行まで飛ばして行けます。なお行末にもレコード長が埋め込まれているのは BACKSPACE 文で逆戻りするためで、順方向にも逆方向にも同じ感じで行をスキップして進んで行けるようになっています。

以下で書式なしの場合について実際の例を見てみます。

ここではまずウォーミングアップに 100 要素の実数配列を 1 行に一気に書き出します。ファイルを rewind 文で巻き戻した後、一気に 100 個のデータを読み込みます。またファイルを巻き戻して、1 行につき 1 個のデータを書き出してゆきます。

次に BACKSPACE 文で 1 行づつ 50 行ばかり逆戻りしてゆきます。そこからまたファイルの最後まで行を読み飛ばしながら行数を数えてゆきます。

ファイル末まで来たのは iostat 調べますが、EOF (end of file) を表す数が iso_fortran_env の中に iostat_end として定義されるようになったので (f08) これを用いてみました。(伝統的に Fortran では EOF を表す数は -1 になっているので、わざわざ無理しなくてもいいんですが。忘れてましたが is_iostat_end() という関数もありました。f08)

    program IOtest
        use, intrinsic :: iso_fortran_env, only : iostat_end
        implicit none
        real :: x(100), y(100)
        integer :: i, k, io, ipos
        
        forall(i = 1:100) x(i) = real(i)
        write(9) x
        rewind(9)
        
        read(9) y
        rewind(9)
        
        
        rewind(9)
        do i = 1, 100
            write(9) y(i)
        end do

        do i = 1, 50
            backspace(9)
        end do
            
        k = 0
        do 
            read(9, iostat = io) 
            if (io == iostat_end) exit
            k = k + 1
        end do
        print *, 'number of data', k
    end program IOtest

実行結果

100 行のデータを書き込んだ後、backspace 文 50 回で 50 行逆戻りしたので、そこから end_of_file まで行を読み飛ばしてゆくと、当然データ数は 50 行分になります。

 number of data          50

おまけ

書式なしフォーマットの内部。

規格で規定されているわけではないけれども、一般に Fortran の書式なしのシーケンシャル・ファイル(順並びファイル)は、各行に対応するレコードの前後に、レコード長が書き込まれています。(最近では 4 バイト整数値で)

前後に書き込まれているのは、空の READ 文や BACKSPACE 文で順方向・逆方向に素早くデータを読み飛ばしてヘッドを動かすためだと思われます。

READ - BACKSPACE と順方向と逆方向で命令が対称になっていないのは歴史的な理由でご愛嬌w

    program IOtest2
        implicit none
        integer :: i, k, ix(3)

        forall(i = 1:3) ix(i) = i
        write(9) ix

        do i = 1, 3
            write(9) ix(i)
        end do    
        close(9)

        open(9, access = 'stream')
        do 
            read(9, end = 99) k 
            print *, k
        end do
99      continue

    end program IOtest2

実行結果 intel fortran 調べ

4バイト整数の要素3の配列と、4バイト整数が3個書き出されているので、以下の様な4バイト整数値がファイルに書き込まれている。

12byte 1, 2, 3 12byte
4byte 1 4byte
4byte 2 4byte
4byte 3 4byte
 

          12
           1
           2
           3
          12
           4
           1
           4
           4
           2
           4
           4
           3
           4
6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?