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` を指定するようにしてください。

コメント