[Fortranのはじめ方] Part17: ファイルの読み書き(OPEN, CLOSE, INQUIRE)

Fortranでファイル操作の基本を学ぼう!📝

プログラムを実行するだけでなく、外部ファイルにデータを保存したり、ファイルからデータを読み込んだりすることは、科学技術計算やデータ処理において非常に重要です。Fortranでは、OPENCLOSEINQUIREといった文を使ってファイルの操作を行います。このセクションでは、これらの基本的な使い方を学びましょう。


Warning: Undefined array key “is_admin” in /home/c2261046/public_html/omomuki-tech.com/wp-content/themes/sango-theme/library/gutenberg/dist/classes/Toc.php on line 113

Warning: Undefined array key “is_category_top” in /home/c2261046/public_html/omomuki-tech.com/wp-content/themes/sango-theme/library/gutenberg/dist/classes/Toc.php on line 118

Warning: Undefined array key “is_top” in /home/c2261046/public_html/omomuki-tech.com/wp-content/themes/sango-theme/library/gutenberg/dist/classes/Toc.php on line 124

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種類があります。

  1. ファイル名を指定する場合: 特定のファイルに関する情報を取得します。
  2. INQUIRE(FILE='ファイル名', 問い合わせ指定子リスト)
  3. ユニット番号を指定する場合: 特定のユニット番号に接続されているファイルに関する情報を取得します。
  4. 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でファイルを操作するための基本的な文である OPENCLOSEINQUIRE を学びました。

  • OPEN: ファイルとプログラムをユニット番号で接続します。ファイルの状態 (STATUS) や操作 (ACTION) を指定できます。
  • CLOSE: ファイルとの接続を解除します。ファイルを保存 (KEEP) するか削除 (DELETE) するか指定できます。
  • INQUIRE: ファイルやユニットの状態(存在、開いているか、名前など)を問い合わせます。

特に IOSTAT 指定子を使ったエラーチェックは、安定したプログラムを作成するために非常に重要です。ファイル操作を行う際は、常にエラーが発生する可能性を考慮し、適切に処理するように心がけましょう。

これらの文をマスターすれば、プログラムで生成したデータをファイルに保存したり、外部のデータファイルを読み込んで計算に利用したりできるようになります。次は、実際にファイルへの読み書きを行う READ 文と WRITE 文、そして書式を指定する FORMAT 文について学んでいきましょう! 💪

📚 参考情報