固定長ファイルインターフェースのパースと照合
目標
固定長電文のファイルをレイアウトどおりにパースし、トレーラーで完全性を検証し、エンコーディング変換・完了フラグ・保管・突合まで、ファイルインターフェースの1サイクルを完成させます。
なぜ重要なのか
ファイル連携は古く見えますが、大量処理と突合のしやすさでは、今も最善です。問題は、失敗の仕方が静かなことです。送信中に切れたファイルをそのまま処理すると、エラーなしに半分だけ反映され、その事実は、月末の締めに「数字が合わない」として発見されます。完了フラグの規約が片方にしかないと、バッチが毎日何も処理せず、何のエラーも出しません。静かに何もしないことが、最も遅く発見されます。トレーラーの検証と突合は、その静かな失敗を、騒がしくするための仕組みです。
ステップ
/opt/lab/fixtures/eai/file/layout.mdを読んで、/root/f/layout.csvを作成してください。1行目はseq,field,start,length,typeです。startは1から始まる位置で、seqの順に並べ替えます。/root/f/parse.shを作成してください。引数を1つ(データファイル)受け取り、Dで始まるデータレコードだけを、次の6つのフィールドをパイプ(|)で区切って出力します。
文字フィールドの前後の空白は除去し、数値フィールドの先頭の0も除去します。(SALE_DT|CUST_ID|CUST_NM|PROD_CD|QTY|AMTREC_TYPEは出力しません。)/opt/lab/fixtures/eai/file/SALES_20260801.datで実行した結果を、/root/f/parsed.txtに保存してください。/root/f/verify.shを作成してください。引数を1つ(データファイル)受け取り、トレーラーの件数と金額合計がデータレコードと一致すれば終了コード0、不一致なら1行目に理由を出力して、0以外の終了コードで終了します。SALES_20260801.dat→ 通過する必要がありますSALES_20260802.dat→ 失敗する必要があります
/opt/lab/fixtures/eai/file/SALES_EUCKR.datをUTF-8に変換して、/root/f/SALES_utf8.datに保存してください。変換後、ハングルが正常に読める必要があります。/root/f/pick.shを作成してください。引数を1つ(ディレクトリ)受け取り、.okフラグファイルが一緒にある.datのファイル名だけを、1行に1つずつ出力します。.okファイル自体は出力しません。/root/f/csvcheck.pyを作成してください。引数を1つ(CSVファイル)受け取り、rows=<데이터 행수> fields=<헤더 필드수> bad=<필드수가 다른 행수>(プレースホルダーは、順にデータの行数、ヘッダーのフィールド数、フィールド数が異なる行数です)を1行で出力します。引用符の中のカンマ・改行を正しく処理する必要があります。/opt/lab/fixtures/eai/file/orders_quoted.csvで実行した結果を、/root/f/csvcheck.txtに保存してください。SALES_20260801.datを/root/f/archive/20260801/の下に、gzipで圧縮して保管してください。元のファイル名に.gzが付いた形である必要があります。/root/f/recon.csvを作成してください。1行目はitem,source,target,diff,resultです。/opt/lab/fixtures/eai/file/SALES_20260801.dat(source)と/opt/lab/fixtures/eai/file/SALES_20260801.csv(target)を比較して、countの行とamountの行の2つを埋めます。resultは、一致すればOK、異なればNGです。
参考
- バイト単位での切り出し:
cut -b 1-8、文字単位:cut -c 1-8 - エンコーディング変換:
iconv -f EUC-KR -t UTF-8 입력 > 출력(プレースホルダーは入力ファイルと出力ファイルです) - 先頭の0の除去:
$((10#$값))(プレースホルダーは値です)またはsed 's/^0*//'(すべて0だと空文字列になる点に注意) - CSVのパースはPythonの
csvモジュールを使ってください。自前で分割すると、引用符の処理で間違えます。 - よくあるミス1: ヘッダー(H)とトレーラー(T)の行を、データとして数えることです。
- よくあるミス2: ハングルがあるフィールドを文字単位で切って、桁がずれることです。
- よくあるミス3:
.okファイル自体を、処理対象の一覧に含めてしまうことです。
レイアウト定義の整理
/opt/lab/fixtures/eai/file/layout.mdを読んで、/root/f/layout.csvを作成してください。
1行目はseq,field,start,length,typeです。
startは1から始まる位置で、seqの順に並べ替えます。
開始位置は1から数えます。前のフィールドの長さの合計に1を足すと、次のフィールドの開始位置です。最後のフィールドの終わりが、レコード全体の長さと合うかを検算してください。
固定長パーサー
/root/f/parse.shを作成してください。引数を1つ(データファイル)受け取り、Dで始まるデータレコードだけを、次の6つのフィールドをパイプ(|)で区切って出力します。
SALE_DT|CUST_ID|CUST_NM|PROD_CD|QTY|AMT
文字フィールドの前後の空白は除去し、数値フィールドの先頭の0も除去します。(REC_TYPEは出力しません。)
/opt/lab/fixtures/eai/file/SALES_20260801.datで実行した結果を、/root/f/parsed.txtに保存してください。
cutは、バイト基準の-bと文字基準の-cが違います。ハングルが混ざると、この違いが結果を変えます。数値フィールドの先頭の0をどう処理するかも、決める必要があります。
トレーラーの検証
/root/f/verify.shを作成してください。引数を1つ(データファイル)受け取り、トレーラーの件数と金額合計がデータレコードと一致すれば終了コード0、不一致なら1行目に理由を出力して、0以外の終了コードで終了します。
SALES_20260801.dat→ 通過する必要がありますSALES_20260802.dat→ 失敗する必要があります
検証は、処理の前に行う必要があります。処理中に行うと、すでに半分が反映された状態になります。件数と合計の両方を見る必要があります。
エンコーディング変換
/opt/lab/fixtures/eai/file/SALES_EUCKR.datをUTF-8に変換して、/root/f/SALES_utf8.datに保存してください。変換後、ハングルが正常に読める必要があります。
受け取ったファイルが文字化けして見えたら、まずエンコーディングを疑います。韓国の対外連携では、ハングルが2バイトになるエンコーディングが、今も使われています。
完了フラグによる選別
/root/f/pick.shを作成してください。引数を1つ(ディレクトリ)受け取り、.okフラグファイルが一緒にある.datのファイル名だけを、1行に1つずつ出力します。
.okファイル自体は出力しません。
フラグのないファイルは、まだ送信中かもしれません。引数でディレクトリを受け取って、処理対象だけを出力するようにしてください。
CSVインターフェースの検証
/root/f/csvcheck.pyを作成してください。引数を1つ(CSVファイル)受け取り、rows=<데이터 행수> fields=<헤더 필드수> bad=<필드수가 다른 행수>(プレースホルダーは、順にデータの行数、ヘッダーのフィールド数、フィールド数が異なる行数です)を1行で出力します。
引用符の中のカンマ・改行を正しく処理する必要があります。
/opt/lab/fixtures/eai/file/orders_quoted.csvで実行した結果を、/root/f/csvcheck.txtに保存してください。
CSVは、引用符の中にカンマと改行が入ることがあります。単純な分割では、フィールド数が間違います。標準のパーサーを使ってください。
処理後の保管
SALES_20260801.datを/root/f/archive/20260801/の下に、gzipで圧縮して保管してください。元のファイル名に.gzが付いた形である必要があります。
日付別のディレクトリに分けて初めて、1つのディレクトリにファイルが数十万個溜まるのを防げます。テキストは圧縮効果が大きいです。
突合表の作成
/root/f/recon.csvを作成してください。1行目はitem,source,target,diff,resultです。
/opt/lab/fixtures/eai/file/SALES_20260801.dat(source)と/opt/lab/fixtures/eai/file/SALES_20260801.csv(target)を比較して、countの行とamountの行の2つを埋めます。
resultは、一致すればOK、異なればNGです。
件数だけが合えば安心しやすいですが、1件が抜けて別の1件が2回入っても、件数は合います。合計も一緒に見てください。