私は推測していますが、可変長レコードをファイルから固定長 COBOL レコードに読み込んでいるようです。COBOL レコードの末尾のがらくたは、あなたに悲しみを与えています。そのジャンクが読み取りごとにどの程度一貫しているかを言うのは難しいです (実際の入力レコード長の境界を超えるデータは技術的に定義されていません)。そのジャンクはWS_AMOUNT_TXT
、UNSTRING
この問題を解決するには、いくつかの方法があります。ここで提示する提案は最適ではないかもしれませんが、単純であり、仕事を成し遂げるはずです。
ステートメントの最後のINTO
フィールドはWS_AMOUNT_TXT
、UNSTRING
末尾のジャンクをすべて受け取るフィールドです。そのがらくたは取り除く必要があります。最後のフィールドで有効な文字は数字と小数点のみであるため、次のようにクリーンアップできます。
PERFORM VARYING WS_I FROM LENGTH OF WS_AMOUNT_TXT BY -1
UNTIL WS_I = ZERO
IF WS_AMOUNT_TXT(WS_I:1) IS NUMERIC OR
WS_AMOUNT_TXT(WS_I:1) = '.'
MOVE ZERO TO WS_I
ELSE
MOVE SPACE TO WS_AMOUNT_TXT(WS_I:1)
END-IF
END-PERFORM
上記のコードの基本的な考え方は、最後のUNSTRING
出力フィールドの末尾から先頭までスキャンし、有効な数字または小数点ではないものをすべてスペースに置き換えることです。有効な数字/10 進数が見つかったら、残りが有効であると仮定してループを終了します。
クリーンアップ後、前の質問NUMVAL
に対する私の回答で概説した組み込み関数を使用して
、WS_AMOUNT_TXT を数値データ型に変換します。
最後に、バッファに残っている可能性のある前回の読み取りから残ったデータを吹き飛ばすMOVE SPACES TO INPUT_REC
前に、1 つのアドバイスがあります。READ
これにより、「長い」レコードの後に非常に「短い」レコードを読み取るときに保護されます。そうしないと、前の読み取りから残ったデータにつまずく可能性があります。
お役に立てれば。
編集可変長ファイルの読み取りに関する質問に対するこの回答に気づきました。可変長入力レコードを使用する方が優れた方法です。実際の入力レコード長を指定すると、次のようなことができます。
UNSTRING INPUT_REC(1:REC_LEN) INTO...
fileの後にREC_LEN
指定された変数はどこにありますか。あなたが遭遇しているすべてのジャンクは、 で定義されているように、レコードの終了後に発生します。上記のように参照変更を使用すると、個々のデータ フィールドを分離する作業を行う前に、それが削除されます。OCCURS DEPENDING ON
INPUT_REC
FD
REC_LEN
UNSTRING
EDIT 2:
で参照変更を使用することはできませんUNSTRING
。くそー...他のいくつかのCOBOL方言では可能ですが、OpenVMS COBOLでは不可能です。次のことを試してください。
MOVE INPUT_REC(1:REC_LEN) TO WS_BUFFER
UNSTRING WS_BUFFER INTO...
最長の入力レコードを保持するのに十分な長さWS_BUFFER
のワーキング ストレージ変数はどこにありますか。短い英数字フィールドを長いフィールドにする場合、宛先フィールドは、残りのスペースを埋めるために使用されるスペース (つまり ) で左揃えになりPIC X
ます。先頭と末尾のスペースは関数に受け入れられるので、まさに必要なものがあります。MOVE
WS_BUFFER
NUMVAL
あなたをこの方向に推し進めるのには理由があります。短いレコードを読み取るときに、レコード バッファの末尾にあるジャンクは定義されていません。そのがらくたの一部が数字または小数点になる可能性があります。これが発生した場合、最初に提案したクリーンアップ ルーチンは失敗します。
編集 3:
結果の WS_AMOUNT_TXT には ^@ はありませんが、それでも ^M があります
ファイル システムは、各レコードの末尾にある <CR> (^M のこと) をデータとして扱っているようです。
読んでいるファイルが Windows プラットフォームからのもので、現在は UNIX プラットフォームで読んでいる場合、問題が説明されます。Windows ではレコードは <CR><LF> で終了しますが、UNIX では <LF> のみで終了します。UNIX ファイル システムは、<CR> をレコードの一部であるかのように扱います。
この場合、読み取られたすべてのレコードの最後に単一の <CR> があることはほぼ確実です。これに対処するには、いくつかの方法があります。
方法 1:既に述べたように、COBOL プログラムで処理する前に、Notepad++ またはその他のツールを使用してファイルを事前編集し、<CR> 文字を削除します。個人的には、これが最善の方法だとは思いません。処理ステップが少ないため、COBOL のみのソリューションを使用することを好みます。
方法 2:処理する前に、各入力レコードから最後の文字を削除します。最後の文字は常に <CR> でなければなりません。レコードを可変長として読み取り、実際の入力レコード長を使用できる場合は、次のことを試してください。
SUBTRACT 1 FROM REC_LEN
MOVE INPUT_REC(1:REC_LEN) TO WS_BUFFER
UNSTRING WS_BUFFER INTO...
方法 3:次のように、UNSTRING 時に <CR> を区切り文字として扱います。
UNSTRING INPUT_REC DELIMITED BY "," OR x"0D"
INTO WS_ID_1, WS_ID_2, WS_CODE, WS_DESCRIPTION, WS_FLAG, WS_AMOUNT_TXT
方法 4:末尾の非数字/非小数点文字をスペースに置き換えて、UNSTRING からの最後の受信フィールドを調整します。この解決策については、この質問の前半で概説しました。オプション (形式 2)INSPECT
を使用してステートメントを調べることもできます。REPLACING
これは、ほとんど同じことを実行できるはずです。すべての x"00" を SPACE に、x"0D" を SPACE に置き換えるだけです。
意志あるところに道あり。上記の解決策のいずれかが機能するはずです。最も使いやすいものを選択してください。