Fortranでファイル操作の基本を学ぼう!
プログラムを実行するだけでなく、外部ファイルにデータを保存したり、ファイルからデータを読み込んだりすることは、科学技術計算やデータ処理において非常に重要です。Fortranでは、OPEN
、CLOSE
、INQUIRE
といった文を使ってファイルの操作を行います。このセクションでは、これらの基本的な使い方を学びましょう。
1. ファイルを開く (OPEN文)
ファイルに対して読み書きを行う前に、まずそのファイルを「開く」必要があります。OPEN
文は、プログラムと外部ファイルを特定の「ユニット番号」と呼ばれる整数値で結びつけます。一度ファイルをユニット番号に接続すれば、以降の読み書き操作(READ
文やWRITE
文)では、ファイル名の代わりにこのユニット番号を使用します。
基本的な構文は以下の通りです。
OPEN(UNIT=整数値, FILE='ファイル名', STATUS='状態', ACTION='操作', IOSTAT=整数変数, ...)
主要な指定子(specifier)を見ていきましょう。
指定子 | 説明 | 例 |
---|---|---|
UNIT=unit_number | 接続するユニット番号を指定します。通常、5 (標準入力) と 6 (標準出力) 以外を選びます。 | UNIT=10 |
FILE='filename' | 接続するファイルの名前を指定します。 | FILE='data.txt' |
STATUS='status' | ファイルの状態を指定します。'OLD' : 既存のファイルを開く。ファイルが存在しない場合はエラー。'NEW' : 新しいファイルを作成する。同名のファイルが存在する場合はエラー。'REPLACE' : 新しいファイルを作成する。同名のファイルが存在する場合は上書きする。'SCRATCH' : 一時的なファイルを作成する。プログラム終了時に自動的に削除される。FILE= 指定子と同時に使えない。'UNKNOWN' (デフォルト): 存在すれば'OLD' 、存在しなければ'NEW' として扱われる。 | STATUS='NEW' |
ACTION='action' | ファイルに対する操作を指定します。'READ' : 読み込み専用で開く。'WRITE' : 書き込み専用で開く。'READWRITE' (デフォルト): 読み書き両用で開く。 | ACTION='WRITE' |
IOSTAT=iostat_variable | OPEN操作の結果を格納する整数変数を指定します。成功した場合は0、エラーが発生した場合は正の整数値が格納されます。エラーハンドリングに不可欠です。 | IOSTAT=ios |
FORM='format' | ファイルの形式を指定します。'FORMATTED' (デフォルト): テキストファイル(書式付き)。'UNFORMATTED' : バイナリファイル(書式なし)。 | FORM='UNFORMATTED' |
ACCESS='access' | アクセス方法を指定します。'SEQUENTIAL' (デフォルト): シーケンシャルアクセス(ファイルの先頭から順に読み書き)。'DIRECT' : ダイレクトアクセス(ファイルの任意の位置を読み書き)。RECL= 指定子でレコード長を指定する必要がある。 | ACCESS='DIRECT' , RECL=100 |
使用例:
PROGRAM open_example IMPLICIT NONE INTEGER :: unit_num, io_status unit_num = 10 ! ユニット番号を10とする ! 'output.txt' という名前で新しいファイルを作成し、書き込み用に開く OPEN(UNIT=unit_num, FILE='output.txt', STATUS='REPLACE', ACTION='WRITE', IOSTAT=io_status) ! エラーチェック IF (io_status /= 0) THEN PRINT *, 'Error opening file! IOSTAT = ', io_status STOP END IF PRINT *, 'File "output.txt" opened successfully for writing on unit ', unit_num ! ... ここでファイルへの書き込み処理を行う ... WRITE(unit_num, *) 'Hello from Fortran!' ! ファイルを閉じる (後述) CLOSE(UNIT=unit_num)
END PROGRAM open_example
2. ファイルを閉じる (CLOSE文)
ファイルの操作が終わったら、必ずCLOSE
文を使ってファイルを「閉じる」必要があります。これにより、プログラムとファイルの接続が解除され、ファイルへの変更が確実に保存されます(OSやシステムによります)。また、使用できるユニット番号の数には限りがあるため、不要になったファイルは速やかに閉じることが推奨されます。
基本的な構文は以下の通りです。
CLOSE(UNIT=整数値, STATUS='状態', IOSTAT=整数変数)
主要な指定子を見ていきましょう。
指定子 | 説明 | 例 |
---|---|---|
UNIT=unit_number | 閉じるファイルのユニット番号を指定します。 | UNIT=10 |
STATUS='status' | ファイルを閉じた後の状態を指定します。'KEEP' (デフォルト、ただしSCRATCHファイルは除く): ファイルを保存する。'DELETE' : ファイルを削除する。'SCRATCH' ファイルを開いた場合のデフォルトは'DELETE' です。 | STATUS='DELETE' |
IOSTAT=iostat_variable | CLOSE操作の結果を格納する整数変数。成功時は0、エラー時は正の値。 | IOSTAT=ios |
使用例:
PROGRAM close_example IMPLICIT NONE INTEGER :: file_unit = 20, io_stat ! 'temp_data.tmp' をSCRATCHファイルとして開く OPEN(UNIT=file_unit, STATUS='SCRATCH', ACTION='READWRITE', IOSTAT=io_stat) IF (io_stat /= 0) THEN PRINT *, 'Error opening scratch file! IOSTAT = ', io_stat STOP END IF WRITE(file_unit, *) 'This is temporary data.' ! ファイルを閉じる (SCRATCHなのでデフォルトでDELETEされる) CLOSE(UNIT=file_unit, IOSTAT=io_stat) IF (io_stat /= 0) THEN PRINT *, 'Error closing file! IOSTAT = ', io_stat ELSE PRINT *, 'Scratch file on unit ', file_unit, ' closed and deleted successfully.' END IF ! 'permanent_data.dat' を作成して閉じる (KEEPされる) OPEN(UNIT=file_unit, FILE='permanent_data.dat', STATUS='REPLACE', IOSTAT=io_stat) IF (io_stat /= 0) THEN PRINT *, 'Error opening permanent_data.dat! IOSTAT = ', io_stat STOP END IF WRITE(file_unit, *) 1.23, 4.56 CLOSE(UNIT=file_unit, STATUS='KEEP', IOSTAT=io_stat) ! STATUS='KEEP'はデフォルトだが明示 IF (io_stat /= 0) THEN PRINT *, 'Error closing permanent_data.dat! IOSTAT = ', io_stat ELSE PRINT *, 'File "permanent_data.dat" closed and kept successfully.' END IF
END PROGRAM close_example
3. ファイルの状態を問い合わせる (INQUIRE文)
INQUIRE
文を使うと、ファイルやユニットに関する様々な情報を取得できます。例えば、「ファイルが存在するか?」「ファイルが開かれているか?」「ファイルの名前は何か?」などを調べることができます。これは、ファイル操作を行う前の事前チェックや、デバッグに役立ちます。
INQUIRE
文は、ファイル名を指定する方法と、ユニット番号を指定する方法の2種類があります。
- ファイル名を指定する場合: 特定のファイルに関する情報を取得します。
- ユニット番号を指定する場合: 特定のユニット番号に接続されているファイルに関する情報を取得します。
INQUIRE(FILE='ファイル名', 問い合わせ指定子リスト)
INQUIRE(UNIT=ユニット番号, 問い合わせ指定子リスト)
よく使われる問い合わせ指定子(inquire specifier)には以下のようなものがあります。
指定子 | 格納する変数型 | 説明 |
---|---|---|
EXIST=logical_variable | LOGICAL | ファイルまたはユニットが存在すれば .TRUE. |
OPENED=logical_variable | LOGICAL | ファイルまたはユニットが開かれていれば .TRUE. |
NUMBER=integer_variable | INTEGER | (FILE指定時) ファイルに接続されているユニット番号。接続されていなければ負の値。 |
NAMED=logical_variable | LOGICAL | ファイルに名前があれば .TRUE. (SCRATCHファイルなどは名前がないので .FALSE. ) |
NAME=character_variable | CHARACTER | (UNIT指定時) ユニットに接続されているファイル名。 |
ACCESS=character_variable | CHARACTER | アクセス方法 ('SEQUENTIAL' , 'DIRECT' , 'UNDEFINED' )。 |
FORM=character_variable | CHARACTER | 形式 ('FORMATTED' , 'UNFORMATTED' , 'UNDEFINED' )。 |
ACTION=character_variable | CHARACTER | 許可されている操作 ('READ' , 'WRITE' , 'READWRITE' , 'UNDEFINED' )。 |
IOSTAT=integer_variable | INTEGER | INQUIRE操作の結果。成功時は0、エラー時は正の値。ファイルが存在しない場合などもエラーになることがある。 |
使用例 (ファイル名指定):
PROGRAM inquire_by_file_example IMPLICIT NONE LOGICAL :: file_exists, file_opened INTEGER :: unit_num, io_stat CHARACTER(LEN=256) :: file_name file_name = 'my_data.txt' ! my_data.txt が存在するかどうかを確認 INQUIRE(FILE=file_name, EXIST=file_exists, IOSTAT=io_stat) IF (io_stat == 0) THEN IF (file_exists) THEN PRINT *, file_name, ' exists.' ! 存在する場合、開かれているか、ユニット番号は何かを確認 INQUIRE(FILE=file_name, OPENED=file_opened, NUMBER=unit_num) IF (file_opened) THEN PRINT *, file_name, ' is opened on unit ', unit_num ELSE PRINT *, file_name, ' is not currently open.' END IF ELSE PRINT *, file_name, ' does not exist.' END IF ELSE PRINT *, 'Error during INQUIRE by file! IOSTAT = ', io_stat END IF
END PROGRAM inquire_by_file_example
使用例 (ユニット番号指定):
PROGRAM inquire_by_unit_example IMPLICIT NONE LOGICAL :: unit_opened, unit_named CHARACTER(LEN=256) :: connected_file CHARACTER(LEN=20) :: access_method, file_form INTEGER :: unit_to_check = 15, io_stat ! まずユニット15を開いてみる (エラーは無視) OPEN(UNIT=unit_to_check, FILE='temp_inquire.dat', STATUS='REPLACE', IOSTAT=io_stat) ! ユニット15の状態を問い合わせる INQUIRE(UNIT=unit_to_check, OPENED=unit_opened, NAMED=unit_named, & & NAME=connected_file, ACCESS=access_method, FORM=file_form, IOSTAT=io_stat) IF (io_stat == 0) THEN IF (unit_opened) THEN PRINT *, 'Unit ', unit_to_check, ' is open.' IF (unit_named) THEN PRINT *, 'Connected file: ', TRIM(connected_file) ELSE PRINT *, 'Connected to an unnamed (SCRATCH?) file.' END IF PRINT *, 'Access method: ', access_method PRINT *, 'Form: ', file_form ! 使ったので閉じる CLOSE(UNIT=unit_to_check) ELSE PRINT *, 'Unit ', unit_to_check, ' is not open.' END IF ELSE PRINT *, 'Error during INQUIRE by unit! IOSTAT = ', io_stat END IF
END PROGRAM inquire_by_unit_example
まとめ
今回は、Fortranでファイルを操作するための基本的な文である OPEN
、CLOSE
、INQUIRE
を学びました。
- OPEN: ファイルとプログラムをユニット番号で接続します。ファイルの状態 (
STATUS
) や操作 (ACTION
) を指定できます。 - CLOSE: ファイルとの接続を解除します。ファイルを保存 (
KEEP
) するか削除 (DELETE
) するか指定できます。 - INQUIRE: ファイルやユニットの状態(存在、開いているか、名前など)を問い合わせます。
特に IOSTAT
指定子を使ったエラーチェックは、安定したプログラムを作成するために非常に重要です。ファイル操作を行う際は、常にエラーが発生する可能性を考慮し、適切に処理するように心がけましょう。
これらの文をマスターすれば、プログラムで生成したデータをファイルに保存したり、外部のデータファイルを読み込んで計算に利用したりできるようになります。次は、実際にファイルへの読み書きを行う READ
文と WRITE
文、そして書式を指定する FORMAT
文について学んでいきましょう!
参考情報
- Fortran Standard Documents (WG5): https://wg5-fortran.org/standards.html (Fortranの規格書へのリンクがあります)
- GFortran Documentation: https://gcc.gnu.org/onlinedocs/gfortran/ (gfortranのマニュアル)