すみませんCOBOL初心者です。
FILE-CONTROL.
SELECT URIAGE-MOKUHYOU ASSIGN TO "c:\dat\mokuhyou.dat"
ORGANIZATION IS INDEXEDACCESS MODE IS RANDOM RECORD KEY IS UM-SHITEN-CODE.
DATADIVISION.
FILESECTION.
FD URIAGE-MOKUHYOU.
01 UM-REC.
05 UM-SHITEN.
10 UM-SHITEN-CODEPIC X(4).
10 UM-SHITEN-MEIPIC X(20).
05 UM-KINGAKUPIC 9(10) OCCURS 12.
WORKING-STORAGESECTION.
01 TSUKIPIC 9(2).
01 WK-SHITEN-CODEPIC X(4).
PROCEDUREDIVISION.
DISPLAY "支店コードを入力してください --> : "
ACCEPT WK-SHITEN-CODE
OPEN INPUT URIAGE-MOKUHYOU
READ URIAGE-MOKUHYOU
INVALID KEY
DISPLAY "ERROR; 支店コード = " WK-SHITEN-CODE
NOT INVALID KEY
DISPLAY WK-SHITEN-CODE " の売上げ目標は " UM-REC
END-READ.
STOP RUN.
というプログラムを作成し、"mokuhyou.dat"という入力ファイルに正しくデータが格納されているのですが、コンパイルは問題なく、実行すると、
JMP0310I-U OPEN ERROR FILE=mokuhyou.dat. 'ACC-METHOD'. PGM=TEST046 ADR=00401258
とまず画面にでて、OKを押すと、
JMP0099I-U FORCED TERMINATION CODE=0310
というエラーになります。
おそらくファイルが正常に読み込めないものと推測されますが、解決法を教えてください。お願いします。
No.3ベストアンサー
- 回答日時:
う~ん、惜しい。
SELECT URIAGE-MOKUHYOU
ASSIGN TO "C:\DAT\MOKUHYOU.TXT"
ORGANIZATION IS SEQUENTIAL.
か、
SELECT URIAGE-MOKUHYOU
ASSIGN TO "C:\DAT\MOKUHYOU.TXT"
ORGANIZATION IS LINE SEQUENTIAL.
にする(行順ファイルがサポートされてて使える場合)
SELECT N-URIAGE-MOKUHYOU
ASSIGN TO "C:\DAT\MOKUHYOU"
ORGANIZATION IS INDEXED
ACCESS MODE IS DYNAMIC
RECORD KEY IS NUM-SHITEN-CODE.
にする。索引ファイルを使う場合、主ファイル名は8文字以内に、拡張子は付けないのが無難。あと、ファイル名は大文字にしとく方が無難(後述)
05 UM-KINGAKU PIC 9(10) OCCURS 12.
の後ろに
05 FILLER PIC X(2).
が必要(改行コードのCRとLFの分)
MOVE UM-REC TO NUM-REC
はやっちゃいけない(テキスト側に改行コードのフィラが増え、テキストファイルと索引ファイルのレコード構造が違ってしまったから。それに各項目ごとに移送してるから不要)
REWRITE NUM-REC
は
WRITE NUM-REC
INVALID KEY
REWRITE NUM-REC
END-WRITE
にする。OUTPUTオープンしてるからファイルは空になってる。つまりレコードは1つも存在しないからREWRITEは出来ない。
「WRITEしてみてINVALID KEYだったらREWRITE」をする理由は、元のテキストファイルに
0001SHITEN-A旧店名、AAに変更済~~~
0001SHITEN-AA~~~~~~~~~~~~
0002SHITEN-B~~~~~~~~~~~~
0003SHITEN-C~~~~~~~~~~~~
のように「同一の支店コードが2つ書いてあった時」のため。REWRITEではなく「同一コードが2つある」とのエラー表示をして終了するのでも良い。
これでダメだとしたら
「使ってるCOBOLに方言があって、テキストファイルを扱う場合のSELECT文に、何か特殊な書き方をしなきゃならない」
か
「『c:\dat\』のように、ドライブやパス指定を書けない」
か
「索引ファイルのファイル名には『n-mokuhyou.dat』のように拡張子は付けちゃいけない」
か
「索引ファイルのファイル名は『n-mokuhyou』のように8文字を超えちゃいけない」
か
「ファイル名に英文字の小文字を含むと問答無用でエラー」
などの制約が存在する場合がある。
特に索引ファイルでの「拡張子は付けない」と「主ファイル名は8文字以内」は注意。これを守らないとCOBOLが内部でキーファイルのファイル名を自動生成する際に、生成に失敗して実行時にOPEN文で予期せぬエラーが出る可能性が。
古いMS-DOSの仕様を引きずってて廃止して欲しい制約なんだが…。
あと「古いMS-DOSの仕様」に関連してか、ファイル名は大文字を使うのが慣例になっている。ファイル名に小文字を使うと動かないCOBOLがあるらしいので。
ありがとうございました。
お礼遅れて申し訳ありませんでした。
実は、言われたとおりやったつもりでしたが、やはりエラーになってしまって、半分あきらめてました。
でも、改めてこちょこちょいじってるうちに成功しました。
そこでまた新たな質問なんですが、
(1)SELECT FILE01 ASSIGN TO "c:\dat\input-file.txt".
(2)SELECT FILE01 ASSIGN TO INPUT-FL.
OPEN INPUT FILE01
というコードについて、(1)は意味が分かるのですが、(2)はどこからどういうファイルをOPENするのですか?多くのサンプルコードは(2)ですが、そのままコンパイルするとエラーになります。
ローカルフォルダのファイルを使用するという考え自体が違うのですか?
毎回基本的な質問で大変恐縮です。
書籍等を買えば載っているのでしょうが、無精者の私にぜひお力をお貸しください。
No.4
- 回答日時:
>(2)SELECT FILE01 ASSIGN TO INPUT-FL.
>OPEN INPUT FILE01
>というコードについて、(1)は意味が分かるのですが、
>(2)はどこからどういうファイルをOPENするのですか?
どこかに
01 INPUT-FL PIC X(80) VALUE "c:\dat\input-file.txt".
の行がありませんか?
それか、どこかに
01 INPUT-FL PIC X(80).
の行があって、OPEN INPUT FILE01の前に
MOVE "c:\dat\input-file.txt" TO INPUT-FL.
って書いてませんか?
普通、SELECT文には、直接ファイル名は指定しないのです。
なぜなら、以下のような手法で、複数のファイルを切り替える事が多いからです。
MOVE "INPUT001" TO INPUT-FL.
PERFORM MAIN-START THRU MAIN-EXIT.
MOVE "INPUT002" TO INPUT-FL.
PERFORM MAIN-START THRU MAIN-EXIT.
MOVE "INPUT003" TO INPUT-FL.
PERFORM MAIN-START THRU MAIN-EXIT.
STOP RUN.
*
MAIN-START.
OPEN INPUT FILE01.
(メインの処理)
CLOSE FILE01.
MAIN-EXIT.
EXIT.
こうしておけば、OPEN前にINPUT-FLにファイル名を入れ直す事で、同じ処理で複数のファイルを繰り返して操作する事が出来ます。
また「オープンするファイル名は、起動時のコマンドラインに書いてある」と言うケースが多く、コマンドラインからファイル名をMOVEしてくる必要性から、ファイル名部分が変数になっているのが普通なのです。
なるほど!大変よく分かりました。
これで、一通りファイル操作の方法が理解できました。
順読みだとファイルの突合せ処理に無駄が多かったですが、索引ファイルだと効率も良いしコードもすっきりしますね!
これから本格的にCOBOLを使った業務をしないといけないので、また何かあったら教えてください。
本当にありがとうございました。
No.2
- 回答日時:
>基本的な質問で恐縮ですが、mokuhyou.datのファイルは自分がテストデータ
>をエディタで編集し、mokuhyou.datの名前で保存しただけなのですが、
>そうではなく、mokuhyou.datは別プログラムから作成すべきということ
>なのでしょうか?
その通りです。
COBOLは以下の4種類のファイルを扱えます。
・レコード順ファイル(テキストファイル)
・行順ファイル(テキストファイル。一部のCOBOLでのみサポート)
・相対ファイル(バイナリファイル)
・索引ファイル(バイナリファイル。データとキーの2つのファイルでセット)
質問者さんのように「特定の値(支店コード)をキーにして、キーで指定したレコードを読み込む場合」は「索引ファイル」を使用します。
この「索引ファイル」は、単純なテキストファイルではなく「レコードファイル」と「キーファイル」に分かれていて、内部は「バイナリファイル」です。
で、エディタなどで書いた1行が固定長のテキストファイルを扱う場合、COBOLでは「レコード順ファイル」を用います。
なお、一部のCOBOLでは「1行が不定長でも良く、レコード終わりは改行コード」と言う、テキストファイルに特化した「行順ファイル」も扱えますが、古いCOBOLではサポートされていません。
そう言った訳で「元データがエディタで書いたテキストファイルで、それをCOBOLで扱う」と言う場合は、以下のようにします(実際の業務で「よくあるパターン」です)
●テキストインポートプログラムを用意する
1.元データのテキストファイルを「レコード順ファイル」で「INPUTオープン」する
2.実際にCOBOLで操作するデータファイルを「索引ファイル」で「I-Oオープン」し「ファイル無しエラー」を検出した場合は「OUTPUTオープン」する。
3.ソースファイルを「READ xxx NEXT」で読む。「AT END節」が実行された場合はソースファイルを最後まで読んだので全ファイルをクローズして終了。
4.読んだレコードの各項目をMOVE命令で書き出しレコードの各項目に移送する(レコード丸ごとMOVEしてはいけない。入力側と出力側で「項目の桁数」が違う可能性がある)
5.「WRITE xxx」で書き出し、もし「INVALID KEY節」が実行されたら、そのキーのレコードは既存なので「REWRITE xxx」する。つまり、レコードが無ければレコードを追加、レコードがあれば更新する事になる。
6.前の「3.」から繰り返す。
●本体のプログラム
1.実際にCOBOLで操作するデータファイルを「索引ファイル」で「I-Oオープン」する。エラーを検出した場合は「データファイルなし」としてプログラム終了
2.キーを指定して(レコードのキー項目に値を入れて)「READ」を行なう。
3.新規のレコードを追加する場合は「WRITE xxx」を、既存のレコードの内容を書き換える場合は「REWRITE」を行なう。
4.クローズして終了。
I-Oオープン、OUTPUTオープンした場合、プログラムを終了する場合は必ず「CLOSE xxx」を行なう事。クローズしないで「STOP RUN」した場合、最悪、最後に書いたレコードがファイルに反映されずに終了します。
ちなみに、COBOLで扱える各ファイルの詳細は、以下のようになります。
・レコード順ファイル
改行コードも含めて固定長であれば、エディタで書いたテキストファイルも読めるが、先頭から順に1レコードづつ読むしか出来ない。
前のレコードに戻ったり、最後のレコードに飛んだりは出来ない。
先頭レコードに戻りたい場合はクローズしてオープンし直す必要がある(REWINDと言う、先頭に戻る文を追加したCOBOLもあるが一般的ではなく、かなり特殊)
索引もキーもなにもないので「同じ内容のレコード」が複数存在する可能性もある。
・行順ファイル(一部のCOBOLでのみサポート)
レコードが固定長ではなく改行コードで区切られる事を除けば、レコード順ファイルと同じ。
・相対ファイル
ファイルの先頭にレコード管理用のヘッダがあり、レコード長は「COBOLが自動で決めた長さ」になっている。
レコードの先頭にはレコード番号がバイナリデータで記録されていて、レコードの各項目もバイナリデータになっている。
テキストファイルではないので、エディタで作る事は不可能。
言うなれば「レコード番号が索引キーになっている索引ファイル」に同等(と言ってもファイルはデータ本体のみで、キーファイルは存在しない)
キーが存在しないのでレコードの重複がチェック出来ないので「同じ内容のレコード」が複数存在する可能性もある。
・索引ファイル
COBOLで最も良く使われるファイル。と言うか、この形式のファイルがあるからCOBOLが使われると言っても過言ではない。
キーを指定する事で、特定のレコードをすぐに呼び出す事が出来る。
「READ xxx NEXT」を使えば「キーを指定せず、次のレコードを読む(オープン直後は先頭レコードを読む)」のも可能なので、レコード順ファイルで行なうような「先頭から最後まで順に処理する」と言う事も可能。
「START」を使うと「指定したキーに最も近いレコード」も探せるので「キーが○○から△△までの間だけ処理する」と言う事も可能になる。
索引キーが「キーファイル」としてデータ本体のファイルと別になっている事が多い。
普通は同一キーのレコード重複は許されないが「RECORD KEY句」に「WITH DUPLICATES」を指定すると、同一キーで複数のレコードを存在させられる。
レコードの先頭には削除フラグがバイナリデータで記録されていて、レコードの各項目もバイナリデータになっている。
テキストファイルではないので、エディタで作る事は不可能。
各レコードの「物理的なファイル位置」は「キーファイル」で管理されているので、レコードの物理的な位置はキーの順番に一致しない。最終レコードがファイルの先頭に存在したり、先頭レコードがファイルの末尾に存在したりする可能性もある。
丁寧なご解答ありがとうございました。
しかし、テキストインポートプログラムを下記のように作成しましたが、一番初めの質問と同じエラーがコンパイル成功後の実行時に発生してしまいます。もう一度、アホな私に原因をお教えいただけないでしょうか?
(補足)
mokhyou.datを読み込み、n-mokuhyou.datに出力しようとしています。
n-mokuhyou.datは存在させず、OPEN OUTPUT で作成しています。
エラーにはなりますが、n-mokuhyou.datは作成され、エディタで覗くと意味不明な文字がいっぱいです。
そのn-mokuhyou.datを使い、本プログラムを実行しても、同じように読込エラーとなります。
FILE-CONTROL.
SELECT URIAGE-MOKUHYOU ASSIGN TO "c:\dat\mokuhyou.dat" .
SELECT N-URIAGE-MOKUHYOU ASSIGN TO "c:\dat\n-mokuhyou.dat"
ORGANIZATION IS INDEXEDACCESS MODE IS DYNAMIC RECORD
KEY IS NUM-SHITEN-CODE.
DATA DIVISION.
FILE SECTION.
FD URIAGE-MOKUHYOU.
01 UM-REC.
05 UM-SHITEN.
10 UM-SHITEN-CODE PIC X(4).
10 UM-SHITEN-MEI PIC X(20).
05 UM-KINGAKU PIC 9(10) OCCURS 12.
FD N-URIAGE-MOKUHYOU.
01 NUM-REC.
05 NUM-SHITEN.
10 NUM-SHITEN-CODE PIC X(4).
10 NUM-SHITEN-MEI PIC X(20).
05 NUM-KINGAKU PIC 9(10) OCCURS 12.
WORKING-STORAGE SECTION.
01 FLG PIC 9 VALUE 0.
01 I PIC 9(2).
PROCEDUREDIVISION.
OPEN INPUT URIAGE-MOKUHYOU
OPEN OUTPUT N-URIAGE-MOKUHYOU
PERFORM UNTIL FLG = 1
READ URIAGE-MOKUHYOU NEXT
AT END
MOVE 1 TO FLG
NOT AT END
MOVE UM-SHITEN-CODE TO NUM-SHITEN-CODE
MOVE UM-SHITEN-MEI TO NUM-SHITEN-MEI
PERFORM VARYING I FROM 1 BY 1 UNTIL I > 10
MOVE UM-KINGAKU(I) TO NUM-KINGAKU(I)
END-PERFORM
MOVE UM-REC TO NUM-REC
REWRITE NUM-REC
END-READ
END-PERFORM
CLOSE URIAGE-MOKUHYOU
CLOSE N-URIAGE-MOKUHYOU
STOP RUN.
No.1
- 回答日時:
まず、mokuhyou.datを作成する際に「ACCESS MODE IS DYNAMIC」で「OPEN OUTPUT」して、データファイルとキーファイルを作成しておく事。
正しく作成されればmokuhyou.datとmokuhyou.idxの2つのファイルが出来上がる筈。拡張子.idxのファイルは「キーファイル」で、これを元に「キーでの検索」が行なわれる。
てゆ~か、ファイルを作成してるプログラムは、元々「ACCESS MODE IS DYNAMIC」でアクセスしてた筈。それを「ACCESS MODE IS RANDOM」でアクセスしようとするから、実行時にオープン文でエラーが起きてる訳で。
で、特定のキーで特定のレコードを読みたいなら「ACCESS MODE IS DYNAMIC」で、キー付きファイルをオープンする事。
×ACCESS MODE IS RANDOM
○ACCESS MODE IS DYNAMIC
実際、特定のキーで特定のレコードを読む場合は、レコードキーに「欲しいレコードのキー値」をセットしておいてから「READ」を行なう。
× OPEN INPUT URIAGE-MOKUHYOU
× READ URIAGE-MOKUHYOU
○ OPEN INPUT URIAGE-MOKUHYOU
○ MOVE WK-SHITEN-CODE TO UM-SHITEN-CODE
○ READ URIAGE-MOKUHYOU
レコードが無ければ「INVALID KEY」節が実行され、あれば「NOT INVALID KEY」節が実行される。
すみません。基本的な質問で恐縮ですが、mokuhyou.datのファイルは自分がテストデータをエディタで編集し、mokuhyou.datの名前で保存しただけなのですが、そうではなく、mokuhyou.datは別プログラムから作成すべきということなのでしょうか?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- PHP PHPのエラーの解消法について教えて下さい。 1 2023/02/06 10:48
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- Windows 10 VirtualBox 7のゲストOSでの物理HDDパーティションのマウント方法 2 2023/05/04 13:01
- ドイツ語 若い頃、聞いたので記憶が少し曖昧ですが、次のドイツ語の原典をご教示ください。(意訳で「死は全てを解決 1 2023/06/15 11:36
- その他(プログラミング・Web制作) VS codeを使って、ラズパイ Picoを動かせる簡単な方法 1 2023/04/27 13:49
- その他(プログラミング・Web制作) Fortranでの出力ファイル 2 2023/03/21 21:25
- その他(プログラミング・Web制作) google formsを使ったタスク依頼フォーム作成におけるご相談 1 2023/06/22 15:55
- Visual Basic(VBA) ユーザーフォームに2つのコンボボックス銀行名「ConboBox1」支店名を「ConboBox2」とし 4 2022/08/03 17:34
- HTML・CSS CSSが効かずどのように指定すれば良いか分からないのでアドバイスお願い致します 2 2023/06/07 12:25
- Visual Basic(VBA) VBAのユーザーフォームのテキストボックスに入力制限をしたい 6 2022/11/15 08:28
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
ファイル書込みで一行もしくは...
-
ADO VBA 実行時エラー3021
-
レコードが存在しなかった場合
-
Accessでレコードの更新を任意...
-
ヘッダレコードとトレーラレコ...
-
[VB6]プログレスバーコントロー...
-
差し込み印刷のレコード数について
-
カレントレコードが無い事を判...
-
ACCESS VBA テーブルデータに...
-
ACCESSで大量の更新を行うと「...
-
サブレンジ分割されたNDB(富士...
-
DataGridViewの、選択されてい...
-
ワードの差込印刷で教えて下さ...
-
固有レコード識別子の選択とは
-
アクセスでレポートの1印刷内...
-
Line Inputで文字化け(助けて...
-
レコードセット(ADO.Recordset)...
-
Access でレコードセレクタが押...
-
COBOLでのランダムアクセス
-
JSPのNULLレコード表示について...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
レコードが存在しなかった場合
-
ADO VBA 実行時エラー3021
-
ファイル書込みで一行もしくは...
-
アクセスでレポートの1印刷内...
-
カレントレコードが無い事を判...
-
差し込み印刷のレコード数について
-
レコードセット(ADO.Recordset)...
-
ワードの差込印刷で教えて下さ...
-
DataGridViewの内容をDBに反映...
-
Access でレコードセレクタが押...
-
DataGridViewの、選択されてい...
-
JSPのNULLレコード表示について...
-
ACCESSで大量の更新を行うと「...
-
[VBA] ADOの Clone と AddNew
-
Access を×ボタンで閉じ...
-
サブレンジ分割されたNDB(富士...
-
ヘッダレコードとトレーラレコ...
-
データセットのレコード更新が...
-
DataGridViewにてセル以外をク...
-
Line Inputで文字化け(助けて...
おすすめ情報