【Fortran学習|初心者向け】Fortranのストリーム入出力で「巨大データ」を効率的に扱う方法

1. 導入: なぜストリーム入出力が重要なのか

数値計算において、大規模なシミュレーション結果をファイルに保存する際、従来のFortranのデフォルト(レコード構造を持つバイナリ形式)では、ファイルサイズが肥大化したり、他のプログラミング言語(PythonやC++など)からデータを読み込む際に手間取ったりすることがよくあります。

「ストリーム入出力」を使うことで、ファイルは単なる「バイト列の連続」として扱われます。これにより、C言語等のバイナリ形式と完全な互換性を持ち、計算結果のチェックポイント保存や、解析ツールへのデータ受け渡しが格段にスムーズになります。

2. 基礎知識: ストリーム入出力とは?

通常、Fortranでファイルを開くと「レコード」という区切りが自動的に付与されます。これは数値計算には便利なのですが、外部ツールとの連携時には邪魔になることがあります。

ストリーム入出力(access=’stream’)は、この「レコードの壁」を取り払い、ファイル内の任意のバイト位置(pos)に直接アクセスすることを可能にします。これにより、データの読み書きが非常にシンプルかつ高速になります。

3. 実装/解決策

ストリーム入出力を用いる際は、ファイルを開く際に `access=’stream’` を指定します。また、`form=’unformatted’` と組み合わせることで、数値データを変換なしでそのままメモリイメージとして書き出すことができます。読み書きの際は `pos=` オプションを使って、何バイト目から操作するかを指定します。

4. サンプルプログラム

以下のコードは、配列のデータをバイナリファイルとして保存し、その後、特定の数値だけを直接読み出すサンプルです。

program stream_io_example
    implicit none
    integer :: i, unit_num
    real(8) :: data(5), val
    
    ! データ生成
    data = [1.0d0, 2.0d0, 3.0d0, 4.0d0, 5.0d0]
    
    ! ファイルを開く(access='stream' がポイント)
    open(10, file='data.bin', access='stream', form='unformatted')
    
    ! データを書き込み
    write(10) data
    
    ! 3番目の値(8バイト×2 = 16バイト目以降)を読み出す
    ! posは1から始まるバイト位置を指定します
    read(10, pos=17) val
    
    print , "3番目の値:", val
    
    close(10)
end program stream_io_example

5. 応用・注意点

ストリーム入出力を使用する上で、初心者が陥りやすい注意点がいくつかあります。

・バイト位置の計算に注意する
`pos` は「バイト単位」です。例えば `real(8)`(倍精度浮動小数点数)を書き込む場合、1つにつき8バイト消費します。3つ目のデータにアクセスしたい場合は、(3-1) 8 + 1 = 17バイト目から読み出す必要があります。

・エンディアンの確認
バイナリ形式はCPUのアーキテクチャ(リトルエンディアンかビッグエンディアンか)に依存します。異なる環境間でファイルをやり取りする場合は、`convert=’little_endian’` などのオプションを `open` 文に追加して、エンディアンを固定することをお勧めします。

・既存データの保護
ストリーム入出力は、既存ファイルの特定箇所だけを上書きすることも可能です。便利ですが、重要なデータを誤って書き換えないよう、書き込み時には慎重に `pos` を指定するようにしてください。

コメント

タイトルとURLをコピーしました