[COBOLのはじめ方] Part13: シーケンシャルファイルの読み書き

COBOL

COBOLでの基本的なファイル操作、シーケンシャルファイルの入出力を学びましょう!

COBOLは、特にビジネスアプリケーションで大量のデータを処理するために広く使われてきました。その中心的な機能の一つがファイル処理です。ここでは、最も基本的なファイル形式であるシーケンシャルファイル(順編成ファイル)の読み書き方法を解説します。

シーケンシャルファイルは、レコード(データの行)がファイルに書き込まれた順序で格納されるファイルです。データを読み出す際も、基本的には先頭から順番に読み出す必要があります。テープメディアの時代から使われている古典的なファイル形式ですが、今でも多くの場面で利用されています。

1. ファイルを使用するための準備 🛠️

COBOLプログラムでファイルを使用するには、いくつかの準備が必要です。主にENVIRONMENT DIVISIONDATA 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 DIVISIONFILE 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 DIVISIONFILE 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 DIVISIONFILE-CONTROLでファイルを定義する。
  • DATA DIVISIONFILE SECTIONでレコード構造を定義する。
  • PROCEDURE DIVISIONOPEN, READ, WRITE, CLOSEを使ってファイルを操作する。
  • READ文ではAT END句でファイルの終わりを検知することが重要。

ファイル処理はCOBOLの根幹をなす機能の一つです。まずはこのシーケンシャルファイルの操作をしっかりマスターしましょう! 💪 次のステップでは、ファイルのOPEN/CLOSE/READ/WRITE操作についてさらに詳しく見ていきます。

コメント

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