OpenVMS
ユーザーズ・マニュアル


前へ 次へ 目次 索引


14.12.1 /END_OF_FILE 修飾子の使用

ファイルから読み込みを行う場合,普通は,ファイルの終端に到達するまで1つ1つのレコードを順に読み込んで処理していきます。READ コマンドと一緒に /END_OF_FILE 修飾子を使用すれば,ループが作成され,ファイルからレコードを読み込んで処理し,すべてのレコードを読み込み終わった時点でループを終了することができます。

/END_OF_FILE 修飾子に指定するラベルは,GOTO コマンドに指定するラベルと同じ規則に従うことに注意してください(GOTO コマンドについての詳細は,第 13 章 を参照してください)。

ループの中で READ コマンドを使用するときには,必ず /END_OF_FILE修飾子を使用するようにします。そうしないと,OpenVMS レコード管理サービス(OpenVMS RMS)によってファイルの終端を示すエラー状態が戻されたときに,コマンド・インタプリタは,現在のON コマンドに指定されるエラー・アクションを実行します。たとえば,OpenVMS RMS がエラー状態 %RMS-E-EOF を戻すと,コマンド・プロシージャが固有のエラー処理方法を設定している場合を除いて,コマンド・プロシージャは終了します。

14.12.2 /INDEX と /KEY 修飾子の使用

索引順編成ファイルからレコードをランダムに読み込むには,READ コマンド修飾子の /INDEX と /KEY を使用します。/INDEX と /KEY 修飾子は,索引の中で指定されたキーを探してそのキーに関連するレコードを戻すことによって,レコードをファイルから読み込むように指定します。索引を指定しないと,主インデックス(0)が使用されます。

レコードをランダムに読み込む場合,/KEY または /INDEX 修飾子を指定せずに READ コマンドを使用すると,ファイルの残りの部分を順に読み込むことができます。

14.12.3 /DELETE 修飾子の使用

READ コマンドと一緒に /DELETE 修飾子を使用すると,索引順編成ファイルからレコードを削除できます。/DELETE 修飾子を指定した場合は,レコードの読み込みが終わってからレコードがファイルから削除されます。/DELETE 修飾子と一緒に /INDEX と /KEY 修飾子を使用すれば,特定のキーによって指定されたレコードを削除できます。

/DELETE,/INDEX,/KEY 修飾子についての詳細は,『OpenVMS DCL ディクショナリ』の READ コマンドの説明を参照してください。

14.13 CLOSE コマンドの使用

CLOSE コマンドは,ファイルを閉じ,OPEN コマンドで作成された論理名の割り当てを解除します。コマンド・プロシージャを終了する場合には,その前にコマンド・プロシージャで開いたすべてのファイルを閉じてください。開いたファイルを閉じなかった場合には,コマンド・プロシージャが終了するときに,ファイルは開かれたままになり,開かれているファイルに割り当てられている論理名は,プロセス論理名テーブルから削除されません。

次の例では,CLOSE コマンドはファイル STATS.DAT を閉じ,論理名 INFILE の割り当てを解除します。


$ OPEN INFILE DISK4:[MURPHY]STATS.DAT 
   .
   .
   .
$ CLOSE INFILE 

14.14 ファイルの変更

この節では,次の 3 種類のファイル変更方法について説明します。

14.14.1 レコードの更新

更新方式を使用してレコードを変更する場合には,ファイル内の一部のレコードだけを変更できます。この方式では,レコードのサイズを変更したり,ファイル内のレコード数を変更することができないため,書式化されたレコード(たとえばデータ・ファイル内のレコード)に対してだけ使用できます。

ファイルの一部だけを変更するには,次の操作を実行します。

手順 操作
1 読み込みアクセスと書き込みアクセスの両用ファイルをオープンする。
2 READ コマンドを使用して,変更したいレコードに到達するまでファイルを読み込む。
3 レコードを変更する。

順編成ファイルでは,このレコードのテキストは元のレコードと同じサイズでなければならない。変更済みのレコードのテキストの方が短い場合は,レコードにスペースを埋め込んで,元のレコードと同じ長さになるまで変更済みのレコードの終わりにスペースを追加する。変更済みレコードのテキストの方が長い場合は,新しいファイルを作成する必要がある。

4 WRITE/UPDATE コマンドを使用して変更したレコードをファイルに書き込む。
5 変更しようとするすべてのレコードの変更が終わるまで,手順 2 〜 4 を繰り返す。
6 CLOSE コマンドを使用してファイルをクローズする。

ファイルをクローズした後,個々のレコードが変更済みであっても,ファイルのバージョン番号は最初と同じである。

次のコマンド・プロシージャは,それぞれのレコードを読み込んで更新することによって,順編成ファイルに変更を加える方法を示しています。


$! Open STATS.DAT and assign it the logical name FILE 
$! 
$ OPEN/READ/WRITE FILE DISK4:[MURPHY]STATS.DAT 
$ BEGIN_LOOP: 
$! Read the next record from FILE into the symbol RECORD 
$     READ/END_OF_FILE=END_LOOP FILE RECORD 
$! Display the record and see if the user wants to change it 
$! If yes, get the new record.  If no, repeat loop 
$! 
$     PROMPT: 
$          WRITE SYS$OUTPUT RECORD 
$          INQUIRE/NOPUNCTUATION OK "Change? Y or N [Y] " 
$          IF OK .EQS. "N" THEN GOTO BEGIN_LOOP 
$          INQUIRE NEW_RECORD "New record" 
$! Compare the old and new records 
$! If old record is shorter than new record, issue an 
$! error message. If old record and new record are the 
$! same length, write the record. Otherwise pad the new 
$! record with spaces so it is correct length 
$! 
$          OLD_LEN = F$LENGTH(RECORD)
$          NEW_LEN = F$LENGTH(NEW_RECORD)
$          IF OLD_LEN .LT. NEW_LEN THEN GOTO ERROR 
$          IF OLD_LEN .EQ. NEW_LEN THEN GOTO WRITE_RECORD 
$          SPACES = "             " 
$          PAD = F$EXTRACT(0,OLD_LEN-NEW_LEN,SPACES)
$          NEW_RECORD = NEW_RECORD + PAD 
$! 
$     WRITE_RECORD: 
$          WRITE/UPDATE FILE NEW_RECORD 
$          GOTO BEGIN_LOOP 
$! 
$     ERROR: 
$          WRITE SYS$OUTPUT "Error -- New record is too long" 
$          GOTO PROMPT 
$! 
$     END_LOOP: 
$          CLOSE FILE 
$          EXIT 

レコードはターミナルに表示され,レコードを変更する必要があるかどうかが尋ねられます。レコードの変更を選択すると,ターミナルから新しいレコードが読み込まれ,新しいレコードの長さと元のレコードの長さとが比較されます。元のレコードの方が長い場合には,新しいレコードにスペースを追加して同じ長さにします。元のレコードの方が短い場合には,エラー・メッセージが表示され,新しいレコードを求めるプロンプトがもう一度出されます。

14.14.2 新しい出力ファイルの作成

ファイルに大きな変更を加えるには,そのファイルを読み込みアクセス用にオープンし,新しいファイルを書き込みアクセス用にオープンします。新しい出力ファイルを作成するので,レコードのサイズを変更したり,レコードを追加したり削除したりできます。

OPEN/WRITE コマンドは,書き込みアクセス用の新しいファイルをオープンします。新しいファイルは元のファイルと同じ名前にすることができ,バージョン番号は,古いファイルのバージョン番号より 1 だけ大きくなります。

注意

読み込み用に正しいファイルがオープンされるように,既存のファイルを読み込みアクセス用にオープンしてから,新しいバージョンを書き込みアクセス用にオープンするようにしなければなりません。

ファイルに変更を加えるには,次の手順に従ってください。

手順 操作
1 該当ファイルを読み込みアクセス用にオープンする。

これは入力ファイルであり,このファイルを変更する。

2 書き込みアクセス用に新しいファイルをオープンする。

これは出力ファイルであり,このファイルを作成する。出力ファイルに入力ファイルと同じ名前を指定すると,出力ファイルは,入力ファイルより1 だけ大きいバージョン番号を持つ。

3 READ コマンドを使用して,変更中のファイルからレコードを 1 つずつ読み込む。

元のファイルからそれぞれのレコードを読み込むときに,レコードをどのように処理するかを決定する。

4 すべてのレコードが終了するまで,レコードの読み込みと処理を続ける。
5 CLOSE コマンドを使用して,入力ファイルと出力ファイルの両方をクローズする。

次の表では,RECORD シンボルに元のファイルから読み込んだレコードが収められます。

レコードが次のような場合 結果
変更なし 新しいファイルに同じシンボルを書き込む。
変更あり INQUIRE コマンドを使用して別のレコードをシンボルに読み込んでから,変更済みのシンボルを新しいファイルに書き込む。
削除された シンボルを新しいファイルに書き込まない。
挿入された ループを使用して,シンボルにレコードを読み込んだり,シンボルを新しいファイルに書き込んだりする。

例:レコードの変更

例:出力ファイルの作成

次の例は,入力ファイルからレコードを読み込み,レコードを処理してから出力ファイルにコピーするコマンド・プロシージャを示しています。


$! Open STATS.DAT for reading and assign it 
$! the logical name INFILE 
$! Open a new version of STATS.DAT for writing 
$! and assign it the logical name OUTFILE 
$! 
$ OPEN/READ INFILE DISK4:[MURPHY]STATS.DAT 
$ OPEN/WRITE OUTFILE DISK4:[MURPHY]STATS.DAT 
$! 
$ BEGIN_LOOP: 
$! Read the next record from INFILE into the symbol RECORD 
$! 
$     READ/END_OF_FILE=END_LOOP INFILE RECORD 
$! Display the record and see if the user wants to change it 
$! If yes, get the new record 
$! If no, write record directly to OUTFILE 
$! 
$     PROMPT: 
$          WRITE SYS$OUTPUT RECORD 
$          INQUIRE/NOPUNCTUATION OK "Change? Y or N [Y] " 
$          IF OK .EQS. "N" THEN GOTO WRITE_RECORD 
$          INQUIRE RECORD "New record" 
$! 
$     WRITE_RECORD: 
$          WRITE OUTFILE RECORD 
$          GOTO BEGIN_LOOP 
$! 
$! Close input and output files 
$     END_LOOP: 
$          CLOSE INFILE 
$          CLOSE OUTFILE 
$          EXIT 

14.14.3 ファイルへのレコードの追加

OPEN/APPEND コマンドは,既存のファイルの終端にレコードを追加します。レコードをファイルに追加するには,次のようにします。

手順 操作
1 OPEN コマンドと一緒に /APPEND 修飾子を使用して,レコード・ポインタをファイルの終端に置く。

/APPEND 修飾子は,ファイルの新しいバージョンは作成しない。

2 WRITE コマンドを使用して新しいデータ・レコードを書き込む。
3 すべてのレコードが終了するまで,レコードを追加し続ける。
4 CLOSE コマンドを使用してファイルをクローズする。

以下のコマンド・プロシージャは STATS.DAT という名前のファイルの末尾にレコードを追加しています。


$! Open STATS.DAT to append files and assign 
$! it the logical name FILE 
$! 
$ OPEN/APPEND FILE DISK4:[MURPHY]STATS.DAT 
$! 
$ BEGIN_LOOP: 
$! Obtain record to be appended and place this 
$! record in the symbol RECORD 
$! 
$     PROMPT: 
$          INQUIRE RECORD - 
           "Enter new record(press RET to quit)" 
$          IF RECORD .EQS. "" THEN GOTO END_LOOP 
$! Write record to FILE 
$! 
$          WRITE FILE RECORD 
$          GOTO BEGIN_LOOP 
$! 
$! Close FILE and exit 
$! 
$     END_LOOP: 
$          CLOSE FILE 
$          EXIT 

14.15 ファイル入出力エラーの処理方法

OPEN,READ,WRITE コマンドのうちのいずれかと一緒に /ERROR 修飾子を使用すると,システム・エラー・メッセージを表示せずに指定されたラベルに制御を渡すことができます。入出力操作中にエラーが生じた場合には,/ERROR 修飾子は他のすべてのエラー制御方式(READ コマンドの/EDN_OF_FILE 修飾子を除く)に優先します。

次の例は,OPEN コマンドと一緒に /ERROR 修飾子を使用しています。


$ OPEN/READ/ERROR=CHECK FILE CONTINGEN.DOC 
   .
   .
   .
$ CHECK: 
$  WRITE SYS$OUTPUT "Error opening file" 

OPEN コマンドは,読み込みモードで CONTINGEN.DOC ファイルをオープンするように要求しています。ファイルをオープンできない場合(たとえば,ファイルが存在しない場合)には,OPEN コマンドはエラー状態を戻して,CHECK ラベルに制御を渡します。

/ERROR 修飾子によって指定されたエラー・パスは,コマンド・レベルに設定されている現在の ON 状態に優先します。エラーが生じて,ターゲット・ラベルに制御が渡されると,システムに予約されているグローバル・シンボル $STATUS にエラー・コードが保持されます。エラー処理ルーチンで F$MESSAGE レキシカル関数を使用すれば,$STATUS のメッセージを表示できます。

以下の例では,F$STATUS レキシカルの内容を表示するためにレキシカル関数 F$MESSAGE が使用されています。


$ OPEN/READ/ERROR=CHECK FILE 'P1' 
   .
   .
   .
$ CHECK: 
$  ERR_MESSAGE = F$MESSAGE($STATUS)
$  WRITE SYS$OUTPUT "Error opening file: ",P1 
$  WRITE SYS$OUTPUT ERR_MESSAGE 
   .
   .
   .

14.15.1 省略時のエラー・アクション

OPEN,READ,WRITE,または CLOSE コマンドを使用しているときにエラーが生じ,エラー・アクションを指定しないと,現在のON コマンド・アクションが有効になります。

READ コマンドがファイルの終端メッセージを受け取った場合のエラー・アクションは,次のようにして決定されます。

14.16 実行フローの制御方法

コマンド・プロシージャでの通常の実行フローは順次です。つまり,ファイルの最後に到達するまで,プロシージャ内のコマンドが順に実行されます。しかし,特定の文を実行するかどうかなど,プロシージャの実行を続行するときの条件を制御することもできます。

この後の節では,次のことについて説明します。

14.16.1 IF コマンドの使用

IF コマンドは,式の値をテストして,式の結果が真の場合にコマンドまたはコマンドのブロックを実行します。式の結果が偽の場合には,次のいずれかになります。

DCL の IF コマンドには,2 つの形式があります。1 つは,第 13 章 で説明されているように IF コマンドに指定された式が真の場合に単独のコマンドを実行する形式です。

DCL にはブロック構造の IF 形式もあります。ブロック構造のIF コマンドは,指定された式が真の場合に複数のコマンドを実行します。ELSE 文を指定すれば,式が偽の場合に 1 つ以上のコマンドを実行することができます。

14.16.2 THEN コマンドの使用

式が真の場合に複数のコマンドを実行するには,動詞(前にドル記号が付いた DCL コマンド)として THEN 文を指定し,残りのブロック構造文の終わりに ENDIF 文を指定します。

次の例では,THEN 文は動詞として使用されています。


$ IF expression 
$   THEN 
$       command 
$       command 
   .
   .
   .
$ ENDIF 


前へ 次へ 目次 索引