COBOLでの基本的なファイル操作、シーケンシャルファイルの入出力を学びましょう!
COBOLは、特にビジネスアプリケーションで大量のデータを処理するために広く使われてきました。その中心的な機能の一つがファイル処理です。ここでは、最も基本的なファイル形式であるシーケンシャルファイル(順編成ファイル)の読み書き方法を解説します。
シーケンシャルファイルは、レコード(データの行)がファイルに書き込まれた順序で格納されるファイルです。データを読み出す際も、基本的には先頭から順番に読み出す必要があります。テープメディアの時代から使われている古典的なファイル形式ですが、今でも多くの場面で利用されています。
1. ファイルを使用するための準備 🛠️
COBOLプログラムでファイルを使用するには、いくつかの準備が必要です。主にENVIRONMENT DIVISIONとDATA DIVISIONでファイルに関する定義を行います。
ENVIRONMENT DIVISIONでの定義
INPUT-OUTPUT SECTION
内のFILE-CONTROL
段落で、プログラム内で使用するファイルと、OS上の実際のファイル(物理ファイル)を結びつけます。
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT file-name ASSIGN TO physical-file-name
ORGANIZATION IS SEQUENTIAL
ACCESS MODE IS SEQUENTIAL.
- SELECT file-name: プログラム内でこのファイルを参照するときの論理名を指定します。
- ASSIGN TO physical-file-name: OS上のファイル名やパスを指定します。指定方法はOSやCOBOL処理系によって異なります。(例: “INPUT.DAT”, “C:\DATA\OUTPUT.TXT”)
- ORGANIZATION IS SEQUENTIAL: ファイル編成がシーケンシャルであることを宣言します。(多くの処理系ではデフォルトなので省略可能な場合もあります)
- ACCESS MODE IS SEQUENTIAL: ファイルへのアクセスモードがシーケンシャルであることを宣言します。(これもデフォルトの場合が多いです)
DATA DIVISIONでの定義
FILE SECTION
で、SELECT
句で定義したファイルのレコード構造を定義します。
DATA DIVISION.
FILE SECTION.
FD file-name.
01 record-name.
05 data-item-1 PIC X(10).
05 data-item-2 PIC 9(5).
05 data-item-3 PIC X(20).
- FD file-name:
FILE SECTION
の開始と、定義対象のファイル(SELECT
句で指定した論理名)を指定します。FDは File Description の略です。 - 01 record-name: ファイルの1レコード全体の名前を定義します。
- 05 data-item-n PIC …: レコード内の各データ項目(フィールド)とそのデータ型、長さを
PIC
句で定義します。
ファイルを読み書きする際には、通常、WORKING-STORAGE SECTION
にファイルレコードと同じ構造の作業域を定義しておくと便利です。
WORKING-STORAGE SECTION.
01 WS-RECORD.
05 WS-DATA-1 PIC X(10).
05 WS-DATA-2 PIC 9(5).
05 WS-DATA-3 PIC X(20).
2. ファイルの操作 (PROCEDURE DIVISION) ⚙️
ファイルの読み書きはPROCEDURE DIVISION
で行います。基本的な操作は OPEN
, READ
, WRITE
, CLOSE
です。
OPEN文: ファイルを開く
ファイルを読み書きする前に、OPEN
文でファイルを開く必要があります。
PROCEDURE DIVISION.
OPEN INPUT file-name. *> 読み込み用に開く
OPEN OUTPUT file-name. *> 書き込み用に開く(新規作成または上書き)
OPEN I-O file-name. *> 更新用に開く(読み書き両用)
OPEN EXTEND file-name. *> 追記用に開く
シーケンシャルファイルの場合、よく使うのはINPUT
(読み込み専用)とOUTPUT
(書き込み専用)です。OUTPUT
で開くと、既存のファイルは通常上書きされます。EXTEND
で開くと、既存ファイルの末尾に追記できます。
READ文: ファイルから読み込む
INPUT
またはI-O
モードで開いたファイルから、1レコードずつデータを読み込みます。
READ file-name
AT END
*> ファイルの終わりに達したときの処理
DISPLAY "End of File reached."
MOVE 'Y' TO WS-EOF-FLAG *> ファイル終了フラグを立てる例
NOT AT END
*> 正常に読み込めたときの処理
MOVE record-name TO WS-RECORD *> FD領域から作業域へ転記
*> ここで読み込んだデータを使った処理を行う
END-READ.
READ file-name
を実行すると、ファイルから次のレコードがDATA DIVISION
のFILE SECTION
で定義したrecord-name
に読み込まれます。- AT END: ファイルの終端(EOF: End Of File)に達したときに実行される処理を記述します。繰り返し読み込み処理を終了させるための重要な部分です。
- NOT AT END: 正常にレコードが読み込めたときに実行される処理を記述します。
WRITE文: ファイルへ書き込む
OUTPUT
, I-O
, EXTEND
モードで開いたファイルへ、1レコードずつデータを書き込みます。
*> 書き込むデータを WORKING-STORAGE SECTION の作業域などに準備する
MOVE WS-DATA-1 TO data-item-1 OF record-name.
MOVE WS-DATA-2 TO data-item-2 OF record-name.
MOVE WS-DATA-3 TO data-item-3 OF record-name.
WRITE record-name.
または、FROM
オプションを使って作業域から直接書き込むこともできます。
*> 書き込むデータを WORKING-STORAGE SECTION の WS-RECORD に準備する
MOVE "VALUE1" TO WS-DATA-1.
MOVE 12345 TO WS-DATA-2.
MOVE "SOME TEXT" TO WS-DATA-3.
WRITE record-name FROM WS-RECORD.
WRITE record-name
は、DATA DIVISION
のFILE SECTION
で定義したrecord-name
の内容をファイルに書き込みます。WRITE record-name FROM identifier
は、identifier
(通常はWORKING-STORAGE SECTION
で定義したレコード構造)の内容をファイルに書き込みます。内部的にはMOVE identifier TO record-name
してから書き込むのと同じです。
CLOSE文: ファイルを閉じる
ファイルの処理が終わったら、必ずCLOSE
文でファイルを閉じます。これにより、書き込みバッファの内容がファイルに反映され、ファイルリソースが解放されます。
CLOSE file-name.
ファイルをCLOSE
し忘れると、データが正しく書き込まれなかったり、他のプログラムがそのファイルにアクセスできなくなったりする可能性があるため、注意が必要です ⚠️。
3. 簡単なサンプルプログラム 📝
簡単な入力ファイルを読み込み、内容を少し変更して出力ファイルに書き出す例を見てみましょう。
入力ファイル (input.dat) の例
AAAAAAAAAA00001DATA FOR AAAAAAAAAA
BBBBBBBBBB00002DATA FOR BBBBBBBBBB
CCCCCCCCCC00003DATA FOR CCCCCCCCC
COBOLプログラム例
IDENTIFICATION DIVISION.
PROGRAM-ID. SEQFILEIO.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT INPUT-FILE ASSIGN TO "input.dat"
ORGANIZATION IS SEQUENTIAL
ACCESS MODE IS SEQUENTIAL.
SELECT OUTPUT-FILE ASSIGN TO "output.dat"
ORGANIZATION IS SEQUENTIAL
ACCESS MODE IS SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD INPUT-FILE.
01 IN-REC.
05 IN-KEY PIC X(10).
05 IN-NUM PIC 9(5).
05 IN-DATA PIC X(20).
FD OUTPUT-FILE.
01 OUT-REC.
05 OUT-KEY PIC X(10).
05 OUT-NUM PIC 9(5).
05 OUT-DATA PIC X(20).
WORKING-STORAGE SECTION.
01 WS-WORK-AREA.
05 WS-EOF-FLAG PIC X(1) VALUE 'N'.
88 EOF VALUE 'Y'. *> 終了フラグ(88レベル項目)
PROCEDURE DIVISION.
MAIN-PROCEDURE.
*> ファイルを開く
OPEN INPUT INPUT-FILE.
OPEN OUTPUT OUTPUT-FILE.
*> ファイル終了フラグを初期化
MOVE 'N' TO WS-EOF-FLAG.
*> 最初のレコードを読み込む (空読み)
READ INPUT-FILE
AT END
MOVE 'Y' TO WS-EOF-FLAG
END-READ.
*> ファイルの終わりまで繰り返し処理
PERFORM UNTIL EOF
*> 読み込んだデータを処理 (ここでは番号を+100する)
MOVE IN-KEY TO OUT-KEY
ADD 100 TO IN-NUM GIVING OUT-NUM
MOVE IN-DATA TO OUT-DATA
*> 出力ファイルへ書き込む
WRITE OUT-REC
*> 次のレコードを読み込む
READ INPUT-FILE
AT END
MOVE 'Y' TO WS-EOF-FLAG
END-READ
END-PERFORM.
*> ファイルを閉じる
CLOSE INPUT-FILE.
CLOSE OUTPUT-FILE.
*> プログラム終了
STOP RUN.
出力ファイル (output.dat) の結果
AAAAAAAAAA00101DATA FOR AAAAAAAAAA
BBBBBBBBBB00102DATA FOR BBBBBBBBBB
CCCCCCCCCC00103DATA FOR CCCCCCCCC
このプログラムは、`input.dat` を1レコードずつ読み込み、数値項目 (`IN-NUM`) に100を加算して `output.dat` に書き出します。ファイルの終わりに達するまで `PERFORM UNTIL EOF` ループで処理を繰り返します。
💡 ポイント: 最初のREAD
をループの前に行い(空読み)、ループ内では処理→書き込み→次の読み込み、という順序にするのが一般的です。これにより、ループの終了条件(EOF)が次のループの開始前に正しく判定されます。
まとめ
今回はCOBOLにおけるシーケンシャルファイルの基本的な読み書き方法を学びました。
ENVIRONMENT DIVISION
のFILE-CONTROL
でファイルを定義する。DATA DIVISION
のFILE SECTION
でレコード構造を定義する。PROCEDURE DIVISION
でOPEN
,READ
,WRITE
,CLOSE
を使ってファイルを操作する。READ
文ではAT END
句でファイルの終わりを検知することが重要。
ファイル処理はCOBOLの根幹をなす機能の一つです。まずはこのシーケンシャルファイルの操作をしっかりマスターしましょう! 💪 次のステップでは、ファイルのOPEN/CLOSE/READ/WRITE操作についてさらに詳しく見ていきます。
コメント