import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.UncheckedIOException; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import dto.Kin02Rec; import dto.Kin03Rec; import dto.Kin04Rec; import dto.ZanendacPar; import dto.ZanmsgacPar; import util.ConvUtil; /** * ============================================================ * 【COBOL→Java】KIN05MAT 打刻休暇照合処理 * ============================================================ * PROGRAM-ID. KIN05MAT → 类 Kin05MatMain(PGMパターン:マッチング(1:N)) * * 使用文件(SELECT ASSIGN → 路径常量): * R01INNFIL(KIN04W01 EDITED-PUNCH F80B) → R01INN_FILE(COPY KIN04REC → dto.Kin04Rec) * R02INNFIL(KIN02W01 LEAVE-DAILY F80B) → R02INN_FILE(COPY KIN02REC → dto.Kin02Rec) * W01OUTFIL(KIN05W01 KIN-LEAVE F160B)→ W01OUT_FILE(COPY KIN03REC → dto.Kin03Rec) * 使用SUB(CALL → 类#execute): * SUB02MSG→Sub02MsgSub / SUB03END→Sub03EndSub * 段落对应: * 0000MAJCOLSOR→run() 1000ITTSOR→initPara() 1100R01INNSOR→readR01Para() * 1200R02INNSOR→readR02Para() 2000MAJSOR→majPara() 2020MATCHSOR→matchPara() * 2030PRIOSOR→prioSor() 2100R01ONLYSOR→r01OnlyPara() 2200R02ONLYSOR→r02OnlyPara() * 3000STPSOR→termPara() 4000MSGOUTSOR→msgOutPara() 9999ABDSOR→abendPara() * * 与原代码的差异(详见 doc\conv\KIN05MAT_对照表.md 疑问·回答记录): * #Q1 照合キー(EMP-ID+DATE)はグループ項目のバイト比較と等価なため、文字列連結で比較。 * #Q2 優先順位選定(2030PRIOSOR)は COBOL の EVALUATE TRUE を if/else で忠実に再現。 * #Q3 COBOL は WRK-BEST-* を 2020MATCHSOR と 1000ITTSOR のみ初期化し、 * R01単独出力(2100R01ONLYSOR)ではリセットしないため、前件マッチの休暇情報が * 継続する不具合がある(設計書 2-1/3-5「R01単独→LEAVE-TYPE='99'」と矛盾)。 * ⇒ Java は【設計書準拠】とし、每条 R01 処理前(majPara先頭)に WRK-BEST-* を * '99'/0 に初期化する(resetBest())。COBOL の不整合は本ファイル内コメントで指摘。 * #Q4 FUNCTION WHEN-COMPILED → 程序启动时刻代替。 */ public class Kin05MatMain { // ==================== コンスタント領域 CNSARA ==================== /** 03 CNS-PRGIDX PIC X(008) VALUE 'KIN05MAT'. */ private static final String CST_PRGIDX = "KIN05MAT"; /** 03 CNS-MSGSTR PIC 9(003) VALUE 001. 開始メッセージ */ private static final int CST_MSGSTR = 1; /** 03 CNS-MSGFIN PIC 9(003) VALUE 002. 終了メッセージ */ private static final int CST_MSGFIN = 2; /** 03 CNS-MSGIINKES PIC 9(003) VALUE 006. 入力件数 */ private static final int CST_MSGIINKES = 6; /** 03 CNS-MSGOUTKES PIC 9(003) VALUE 007. 出力件数 */ private static final int CST_MSGOUTKES = 7; /** 03 CNS-MSGKEYINF PIC 9(003) VALUE 033. コンパイル日時 */ private static final int CST_MSGKEYINF = 33; /** 03 CNS-KN0002 PIC 9(001) VALUE 2. */ private static final int CST_KN0002 = 2; /** 03 CNS-ABD999 PIC 9(003) VALUE 999. */ private static final int CST_ABD999 = 999; /** 03 CNS-NO-LEAVE PIC X(002) VALUE '99'. 休暇なし */ private static final String CST_NO_LEAVE = "99"; /** 03 CNS-LEAVE-01 PIC X(002) VALUE '01'. */ private static final String CST_LEAVE_01 = "01"; /** 03 CNS-LEAVE-02 PIC X(002) VALUE '02'. */ private static final String CST_LEAVE_02 = "02"; /** 03 CNS-LEAVE-03 PIC X(002) VALUE '03'. */ private static final String CST_LEAVE_03 = "03"; /** 03 CNS-LEAVE-04 PIC X(002) VALUE '04'. */ private static final String CST_LEAVE_04 = "04"; // ==================== ファイル定義(SELECT ASSIGN 相当) ==================== /** SELECT R01INNFIL ASSIGN TO KIN04W01.(EDITED-PUNCH入力) */ private static final String R01INN_FILE = "data/KIN04W01.dat"; /** SELECT R02INNFIL ASSIGN TO KIN02W01.(LEAVE-DAILY入力) */ private static final String R02INN_FILE = "data/KIN02W01.dat"; /** SELECT W01OUTFIL ASSIGN TO KIN05W01.(KIN-LEAVE出力) */ private static final String W01OUT_FILE = "data/KIN05W01.dat"; // ==================== カウンタ領域 CUNARA(COMP-3 → long) ==================== /** 03 CUN-R01INN PIC S9(009) COMP-3 VALUE ZERO. */ private long cunR01Inn; /** 03 CUN-R02INN PIC S9(009) COMP-3 VALUE ZERO. */ private long cunR02Inn; /** 03 CUN-W01OUT PIC S9(009) COMP-3 VALUE ZERO. */ private long cunW01Out; // ==================== 作業領域 WRKARA ==================== /** 03 WS-R01-STATUS PIC X(002).(OPENチェック用、Javaは例外で代替) */ private String wsR01Status = "00"; /** 03 WS-R02-STATUS PIC X(002). */ private String wsR02Status = "00"; /** 03 WS-W01-STATUS PIC X(002). */ private String wsW01Status = "00"; /** 03 WRK-R01EOF PIC X(001). 読込フラグ */ private String wrkR01Eof = "0"; /** 03 WRK-R02EOF PIC X(001). 読込フラグ */ private String wrkR02Eof = "0"; /** 03 WRK-R01KEY(EMP-ID 8 + DATE 8) */ private String wrkR01Key = ""; /** 03 WRK-R02KEY(EMP-ID 8 + DATE 8) */ private String wrkR02Key = ""; /** 03 WRK-BEST-TYPE PIC X(002). 選定休暇種別 */ private String wrkBestType = CST_NO_LEAVE; /** 03 WRK-BEST-STR-TIME PIC 9(004). */ private int wrkBestStrTime; /** 03 WRK-BEST-END-TIME PIC 9(004). */ private int wrkBestEndTime; /** 03 WRK-BEST-APPL-ID PIC 9(009). */ private int wrkBestApplId; /** 03 WRK-BEST-FOUND PIC X(001). 選定済フラグ */ private String wrkBestFound = "0"; /** 88 WRK-BEST-IS-FOUND VALUE '1'. */ private boolean isBestFound() { return "1".equals(wrkBestFound); } // ==================== サブプログラム連絡領域(LINKAGE COPY → DTO) ==================== /** COPY ZANMSGAC.(SUB02MSG用) */ private final ZanmsgacPar m00MhoPar = new ZanmsgacPar(); /** COPY ZANENDAC.(SUB03END用) */ private final ZanendacPar e01AbdPar = new ZanendacPar(); // ==================== 入出力レコード(FILE SECTION → DTO) ==================== /** FD R01INNFIL の 01 R01INNREC.(現在レコードバッファ) */ private final Kin04Rec r01 = new Kin04Rec(); /** FD R02INNFIL の 01 R02OUTREC.(現在レコードバッファ) */ private final Kin02Rec r02 = new Kin02Rec(); /** FD W01OUTFIL の 01 W01OUTREC. */ private final Kin03Rec w01 = new Kin03Rec(); // ==================== ファイルハンドル(OPEN/CLOSE 相当) ==================== private BufferedReader r01InnFil; private BufferedReader r02InnFil; private PrintWriter w01OutFil; /** 入力ファイルパス(R01/R02/W01)。引数で上書き可。 */ private final String r01InnFile; private final String r02InnFile; private final String w01OutFile; // ==================== PROCEDURE DIVISION ==================== public static void main(String[] args) { final String r1 = (args != null && args.length > 0) ? args[0] : R01INN_FILE; final String r2 = (args != null && args.length > 1) ? args[1] : R02INN_FILE; final String w1 = (args != null && args.length > 2) ? args[2] : W01OUT_FILE; new Kin05MatMain(r1, r2, w1).run(); // PERFORM 0000MAJCOLSOR 相当 } /** 引数付コンストラクタ:各ファイルパスを指定(テスト等で使用)。 */ public Kin05MatMain(final String r01InnFile, final String r02InnFile, final String w01OutFile) { this.r01InnFile = r01InnFile; this.r02InnFile = r02InnFile; this.w01OutFile = w01OutFile; } /** * 段落 0000MAJCOLSOR:制御処理。 * PERFORM 1000ITTSOR → PERFORM 2000MAJSOR UNTIL R01-EOF → PERFORM 3000STPSOR → GOBACK. */ private void run() { try { initPara(); while (!"1".equals(wrkR01Eof)) { // PERFORM 2000MAJSOR UNTIL WRK-R01-EOF majPara(); } termPara(); } finally { closeFiles(); } } /** * 段落 1000ITTSOR:初期処理。 * 開始メッセージ→コンパイル日時→BEST領域初期化→OPEN→OPENチェック→初回読込。 */ private void initPara() { // *** 開始メッセージ出力 msgOutPara(CST_MSGSTR, null, null); // *** コンパイル日時出力 ※疑问#Q4:WHEN-COMPILED→启动时刻代替 String compiled = LocalDateTime.now() .format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")); msgOutPara(CST_MSGKEYINF, compiled, "COMPILED"); // *** ワークエリア初期化 INITIALIZE WRKARA. wrkR01Eof = "0"; wrkR02Eof = "0"; wrkR01Key = ""; wrkR02Key = ""; // *** BEST領域初期化(R01のみ出力時に使用) wrkBestFound = "0"; // MOVE '0' TO WRK-BEST-FOUND. wrkBestType = CST_NO_LEAVE; // MOVE CNS-NO-LEAVE TO WRK-BEST-TYPE. wrkBestStrTime = 0; // MOVE ZERO TO WRK-BEST-STR-TIME. wrkBestEndTime = 0; // MOVE ZERO TO WRK-BEST-END-TIME. wrkBestApplId = 0; // MOVE ZERO TO WRK-BEST-APPL-ID. // *** 入出力ファイル OPEN INPUT R01/R02 / OUTPUT W01. openFiles(); // *** OPENチェック(STATUS≠'00' → ABEND 999) if (!"00".equals(wsR01Status) || !"00".equals(wsR02Status) || !"00".equals(wsW01Status)) { abendPara(); } // *** R01/R02を読み込み readR01Para(); readR02Para(); } /** * 段落 1100R01INNSOR:##R01##読込処理。 * READ AT END / NOT AT END のマッピング。 */ private void readR01Para() { try { String line = r01InnFil.readLine(); if (line == null) { wrkR01Eof = "1"; // AT END: MOVE '1' TO WRK-R01EOF. } else { r01.fromRecordLine(line); // FD R01INNREC への転送. cunR01Inn++; // ADD 1 TO CUN-R01INN. } } catch (IOException e) { throw new UncheckedIOException(e); // READ異常 ≈ ABEND } } /** * 段落 1200R02INNSOR:##R02##読込処理。 * READ AT END / NOT AT END のマッピング. AT END→EOF、NOT AT END→件数++. */ private void readR02Para() { try { String line = r02InnFil.readLine(); if (line == null) { wrkR02Eof = "1"; // AT END: MOVE '1' TO WRK-R02EOF. } else { r02.fromRecordLine(line); // FD R02OUTREC への転送. cunR02Inn++; // ADD 1 TO CUN-R02INN. } } catch (IOException e) { throw new UncheckedIOException(e); // READ異常 ≈ ABEND } } /** * 段落 2000MAJSOR:主処理(マッチング制御)。 * R01キー設定→R02キー設定(有効時)→EVALUATE TRUE で3分岐。 */ private void majPara() { // *** 設計書準拠:每条打刻(R01)は独立に判定。COBOL(KIN05MAT.cbl)は // WRK-BEST-* を 2020MATCHSOR と 1000ITTSOR のみ初期化し、 // R01単独出力(2100R01ONLYSOR)ではリセットしないため、前件マッチの // 休暇情報が継続する不具合がある。Java は設計書意図(='99')どおり、 // 每条 R01 処理前に WRK-BEST-* を初期化する。 resetBest(); // *** R01キー設定 setR01Key(); // *** R02キー設定(有効な場合) if (!"1".equals(wrkR02Eof)) { setR02Key(); } // *** EVALUATE TRUE マッチング3分岐(COBOL の WHEN 順序を if/else で再現) if ("1".equals(wrkR02Eof)) { // WHEN WRK-R02-EOF → R01のみ出力+R01次読込 r01OnlyPara(); readR01Para(); } else if (wrkR01Key.compareTo(wrkR02Key) < 0) { // WHEN WRK-R01KEY < WRK-R02KEY → R01のみ出力+R01次読込 r01OnlyPara(); readR01Para(); } else if (wrkR01Key.compareTo(wrkR02Key) == 0) { // WHEN WRK-R01KEY = WRK-R02KEY → マッチング処理+R01次読込 matchPara(); readR01Para(); } else { // WHEN WRK-R01KEY > WRK-R02KEY → R02のみスキップ+R02次読込 r02OnlyPara(); readR02Para(); } } /** WRK-R01KEY = R01EMP-ID(8) + R01WORK-DATE(8)(グループ比較と等価)。 */ private void setR01Key() { wrkR01Key = r01.getEmpId() + r01.getWorkDate(); } /** WRK-R02KEY = R02EMP-ID(8) + R02DATE(8)(グループ比較と等価)。 */ private void setR02Key() { wrkR02Key = r02.getEmpId() + ConvUtil.padLeftZero(r02.getDate(), 8); } /** * WRK-BEST-* 初期化('99'/0)。 * 設計書(KIN05MAT)準拠:每条打刻(R01)の処理前に実施し、前件マッチの * 休暇情報が継続しないよう保証する。COBOL は本初期化を 2020MATCHSOR と * 1000ITTSOR のみに記述し R01単独出力で漏れたため、無休假打刻に前件の * 休暇種別が残る不具合がある(#Q3)。 */ private void resetBest() { wrkBestFound = "0"; // MOVE '0' TO WRK-BEST-FOUND. wrkBestType = CST_NO_LEAVE; // MOVE CNS-NO-LEAVE TO WRK-BEST-TYPE. wrkBestStrTime = 0; // MOVE ZERO TO WRK-BEST-STR-TIME. wrkBestEndTime = 0; // MOVE ZERO TO WRK-BEST-END-TIME. wrkBestApplId = 0; // MOVE ZERO TO WRK-BEST-APPL-ID. } /** * 段落 2020MATCHSOR:マッチング処理(N:1ループレ)。 * 一致キーの全R02を読込み、最適休暇を選定した上で KIN-LEAVE 出力。 * ※ majPara() 先頭の resetBest() で既に '99'/0 初期化済だが、COBOL 互換の * 位置でも再初期化(冪等)。設計書準拠の挙動は majPara() 側で保証される。 */ private void matchPara() { // *** 選定領域初期化(majPara() での初期化と同一内容) resetBest(); // *** N:1ループ 一致するR02を全件処理 while (true) { if ("1".equals(wrkR02Eof)) { break; // WRK-R02-EOF } if (!wrkR01Key.equals(wrkR02Key)) { break; // WRK-R01KEY < WRK-R02KEY OR WRK-R01KEY > WRK-R02KEY } // *** ベスト選定 if (!isBestFound()) { // 初回 → ベストとして保持 wrkBestFound = "1"; // MOVE '1' TO WRK-BEST-FOUND. wrkBestType = r02.getLeaveType(); wrkBestStrTime = r02.getStartTime(); wrkBestEndTime = r02.getEndTime(); wrkBestApplId = r02.getApplId(); } else { prioSor(r02.getLeaveType(), r02.getStartTime(), r02.getEndTime(), r02.getApplId()); } // *** R02次読込 readR02Para(); // *** R02キー再設定(有効な場合) if (!"1".equals(wrkR02Eof)) { setR02Key(); } } // *** KIN-LEAVE出力(R01のみ出力サブルーチンを共用) r01OnlyPara(); } /** * 段落 2030PRIOSOR:優先順位判定。 * 優先順位 01 > 02 > 03 > 04。同種別は APPL-ID の小さい方を採用。 * COBOL の EVALUATE TRUE を if/else で忠実に再現(WHEN OTHER→CONTINUE)。 */ private void prioSor(final String r02Type, final int r02Str, final int r02End, final int r02Appl) { // EVALUATE TRUE(R02LEAVE-TYPE で分岐) if (CST_LEAVE_01.equals(r02Type)) { if (!CST_LEAVE_01.equals(wrkBestType)) { wrkBestType = r02Type; wrkBestStrTime = r02Str; wrkBestEndTime = r02End; wrkBestApplId = r02Appl; } else if (r02Appl < wrkBestApplId) { wrkBestStrTime = r02Str; wrkBestEndTime = r02End; wrkBestApplId = r02Appl; } } else if (CST_LEAVE_02.equals(r02Type)) { if (CST_LEAVE_01.equals(wrkBestType)) { // CONTINUE(01 が優先) } else if (CST_LEAVE_02.equals(wrkBestType)) { if (r02Appl < wrkBestApplId) { wrkBestStrTime = r02Str; wrkBestEndTime = r02End; wrkBestApplId = r02Appl; } } else { wrkBestType = r02Type; wrkBestStrTime = r02Str; wrkBestEndTime = r02End; wrkBestApplId = r02Appl; } } else if (CST_LEAVE_03.equals(r02Type)) { if (CST_LEAVE_01.equals(wrkBestType)) { // CONTINUE } else if (CST_LEAVE_02.equals(wrkBestType)) { // CONTINUE } else if (CST_LEAVE_03.equals(wrkBestType)) { if (r02Appl < wrkBestApplId) { wrkBestStrTime = r02Str; wrkBestEndTime = r02End; wrkBestApplId = r02Appl; } } else { wrkBestType = r02Type; wrkBestStrTime = r02Str; wrkBestEndTime = r02End; wrkBestApplId = r02Appl; } } else if (CST_LEAVE_04.equals(r02Type)) { if (CST_LEAVE_01.equals(wrkBestType)) { // CONTINUE } else if (CST_LEAVE_02.equals(wrkBestType)) { // CONTINUE } else if (CST_LEAVE_03.equals(wrkBestType)) { // CONTINUE } else if (CST_LEAVE_04.equals(wrkBestType)) { if (r02Appl < wrkBestApplId) { wrkBestStrTime = r02Str; wrkBestEndTime = r02End; wrkBestApplId = r02Appl; } } else { wrkBestType = r02Type; wrkBestStrTime = r02Str; wrkBestEndTime = r02End; wrkBestApplId = r02Appl; } } else { // WHEN OTHER → CONTINUE(未知種別は無視) } } /** * 段落 2100R01ONLYSOR:R01のみ出力(またはマッチ結果出力)。 * 打刻情報(1-80B)+休暇情報(81-160B、WRK-BEST-* を使用)を KIN-LEAVE に出力。 */ private void r01OnlyPara() { // *** KIN-LEAVEレコード編集 w01.reset(); // INITIALIZE W01OUTREC. // *** 打刻情報(1-80B) w01.setEmpId(r01.getEmpId()); // MOVE R01EMP-ID TO W01EMP-ID. w01.setWorkDate(r01.getWorkDate()); // MOVE R01WORK-DATE TO W01WORK-DATE. w01.setStrTime(r01.getStrTime()); // MOVE R01STR-TIME TO W01STR-TIME. w01.setEndTime(r01.getEndTime()); // MOVE R01END-TIME TO W01END-TIME. w01.setDeptId(r01.getDeptId()); // MOVE R01DEPT-ID TO W01DEPT-ID. w01.setTerminal(r01.getTerminal()); // MOVE R01TERMINAL TO W01TERMINAL. // *** 休暇情報(81-160B) w01.setLeaveType(wrkBestType); // MOVE WRK-BEST-TYPE TO W01LEAVE-TYPE. w01.setLeaveStrTime(wrkBestStrTime); // MOVE WRK-BEST-STR-TIME TO W01LEAVE-STR-TIME. w01.setLeaveEndTime(wrkBestEndTime); // MOVE WRK-BEST-END-TIME TO W01LEAVE-END-TIME. w01.setLeaveHours(0); // MOVE ZERO TO W01LEAVE-HOURS. w01.setApplicationId(wrkBestApplId); // MOVE WRK-BEST-APPL-ID TO W01APPLICATION-ID. writeW01(); // WRITE W01OUTREC./ADD 1 TO CUN-W01OUT. } /** * 段落 2200R02ONLYSOR:R02のみスキップ(該当打刻のない休暇レコードは出力しない)。 */ private void r02OnlyPara() { // PERFORM 1200R02INNSOR は呼出元(majPara)で実施済(CONTINUE)。 } /** * 段落 3000STPSOR:終了処理。 * CLOSE→入出力件数メッセージ×3→終了メッセージ。 */ private void termPara() { // *** 入出力ファイル CLOSE closeFiles(); // *** 入出力ファイル件数出力(数値→X(30)転送は9桁ゼロ埋め表示形) msgOutPara(CST_MSGIINKES, "KIN04W01", ConvUtil.padLeftZero(cunR01Inn, 9)); msgOutPara(CST_MSGIINKES, "KIN02W01", ConvUtil.padLeftZero(cunR02Inn, 9)); msgOutPara(CST_MSGOUTKES, "KIN05W01", ConvUtil.padLeftZero(cunW01Out, 9)); // *** 終了メッセージ出力 msgOutPara(CST_MSGFIN, null, null); } /** * 段落 4000MSGOUTSOR:メッセージ編集出力処理。 * M00UMKDATS22-03(1:1)/-04(1:1) に '2'、-05 にプログラムIDを設定し SUB02MSG を呼ぶ。 */ private void msgOutPara(final int msgCod, final String p1, final String p2) { m00MhoPar.reset(); // INITIALIZE M00MHOPAR. m00MhoPar.setM00MsgCod(msgCod); // MOVE ... TO M00MSGCOD. if (p1 != null) { m00MhoPar.setM00Umkdats2201(p1); // MOVE ... TO M00UMKDATS22-01. } if (p2 != null) { m00MhoPar.setM00Umkdats2202(p2); // MOVE ... TO M00UMKDATS22-02. } // MOVE CNS-KN0002 TO M00UMKDATS22-03(1:1).(参照修改→先頭1桁上書き、残り29桁はSPACE) m00MhoPar.setM00Umkdats2203(ConvUtil.padRight(Integer.toString(CST_KN0002), 30)); m00MhoPar.setM00Umkdats2204(ConvUtil.padRight(Integer.toString(CST_KN0002), 30)); m00MhoPar.setM00Umkdats2205(CST_PRGIDX); // MOVE CNS-PRGIDX TO ...-05. Sub02MsgSub.execute(m00MhoPar); // CALL 'SUB02MSG' USING M00MHOPAR. } /** * 段落 9999ABDSOR:ABEND処理。 * MOVE 999 TO E01ABDCOD./CALL 'SUB03END' USING E01ABDPAR. */ private void abendPara() { e01AbdPar.reset(); e01AbdPar.setE01AbdCod(CST_ABD999); // MOVE CNS-ABD999 TO E01ABDCOD. Sub03EndSub.execute(e01AbdPar); // CALL 'SUB03END'. } // ==================== ファイル操作補助(OPEN/CLOSE/WRITE 相当) ==================== /** OPEN INPUT R01INNFIL/R02INNFIL / OUTPUT W01OUTFIL(失敗時は STATUS='99'→ABEND)。 */ private void openFiles() { try { r01InnFil = new BufferedReader( new InputStreamReader(new FileInputStream(r01InnFile), "UTF-8")); r02InnFil = new BufferedReader( new InputStreamReader(new FileInputStream(r02InnFile), "UTF-8")); w01OutFil = new PrintWriter( new OutputStreamWriter(new FileOutputStream(w01OutFile), "UTF-8")); } catch (IOException e) { // OPEN失敗相当:FILE STATUS ≠ '00'(後続の OPENチェックで ABEND 999) wsR01Status = "99"; wsR02Status = "99"; wsW01Status = "99"; } } /** WRITE W01OUTREC./ADD 1 TO CUN-W01OUT. */ private void writeW01() { w01OutFil.println(w01.toRecordLine()); cunW01Out++; } /** CLOSE R01INNFIL R02INNFIL W01OUTFIL. */ private void closeFiles() { closeQuiet(r01InnFil); closeQuiet(r02InnFil); closeQuiet(w01OutFil); r01InnFil = null; r02InnFil = null; w01OutFil = null; } private static void closeQuiet(final Object handle) { try { if (handle instanceof BufferedReader) { ((BufferedReader) handle).close(); } else if (handle instanceof PrintWriter) { ((PrintWriter) handle).close(); } } catch (IOException e) { // CLOSE異常は無視(原程序もFILE STATUS未管理) } } }