概要

全銀フォーマットは、全国銀行協会連合会(全銀協)が定めた銀行間データ交換の標準フォーマットです。総合振込、給与振込、口座振替など、企業が銀行へ振込データを送る際に広く使われており、多くの業務システムで生成処理が求められます。フォーマットはヘッダ(レコード区分1)、データ(区分2)、トレーラ(区分8)、エンド(区分9)の4種別で構成され、各レコードは120バイト固定長です。文字コードは JIS X 0201(半角カナ・英数字)で、エンコーディングには Shift_JIS を使用します。数値フィールドは右詰めゼロ埋め、文字フィールドは左詰めスペース埋めという規則があり、1バイトでもずれると銀行側で受付エラーになります。この記事では、全銀仕様書に基づいたレコード生成処理を Pure Java で実装し、フィールドごとのバイト長・パディング規則・よくある実装ミスを整理します。トレーラの合計件数・合計金額によるデータ整合性チェックの仕組みも含め、実務でそのまま使える形に仕上げます。

使いどころ

月次の総合振込データを基幹システムから生成し、銀行のファームバンキングへ送信する

給与振込バッチで従業員の口座情報と支給額を全銀フォーマットに変換する

取引先への支払データを経理システムから全銀形式でエクスポートする

口座振替の請求データを全銀フォーマットで作成し、収納代行サービスへ連携する

テスト環境で全銀データのダミーファイルを生成し、受入テストに使用する

コード例

全銀フォーマット(総合振込)のレコード生成
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

/**
 * 全銀フォーマット(総合振込)のレコード生成サンプル。
 *
 * 全国銀行協会連合会の仕様に基づき、以下の4種別レコードを生成する:
 *   ヘッダ  (レコード区分: 1)120バイト — ファイル先頭に1件
 *   データ  (レコード区分: 2)120バイト — 振込1件につき1レコード
 *   トレーラ(レコード区分: 8)120バイト — 合計件数・合計金額
 *   エンド  (レコード区分: 9)120バイト — ファイル終端
 *
 * パディング規則:
 *   数値フィールド → 右詰め・前ゼロ埋め(例: 金額 1500000 → "0001500000")
 *   文字フィールド → 左詰め・後ろスペース埋め(例: 銀行名 "ミズホ" → "ミズホ          ")
 *
 * 文字コード: JIS X 0201(半角カナ・英数字)、Shift_JIS エンコーディング
 */
public class ZenginFormatGenerator {

    /** Shift_JIS エンコーディング(全銀フォーマットの標準文字コード) */
    private static final Charset SHIFT_JIS = Charset.forName("Shift_JIS");

    // ── 振込データを record で定義 ──────────────────────────
    record TransferData(
        String bankCode,       // 振込先銀行番号(4桁・数値)
        String bankName,       // 振込先銀行名(15桁・半角カナ)
        String branchCode,     // 振込先支店番号(3桁・数値)
        String branchName,     // 振込先支店名(15桁・半角カナ)
        String accountType,    // 預金種目(1桁: 1=普通, 2=当座, 4=貯蓄)
        String accountNumber,  // 口座番号(7桁・数値)
        String accountHolder,  // 受取人名(30桁・半角カナ)
        long amount            // 振込金額(10桁・数値)
    ) {}

    // ── 右詰めゼロ埋め(数値フィールド用) ──────────────────
    // 全銀仕様: 数値フィールドは右詰め・前ゼロ埋め
    // 例: zeroPad(1500000, 10) → "0001500000"
    static String zeroPad(long value, int length) {
        return ("%" + "0" + length + "d").formatted(value);
    }

    // ── 左詰めスペース埋め(文字フィールド用) ──────────────
    // 全銀仕様: 文字フィールドは左詰め・後ろスペース埋め
    // 例: spacePad("ミズホ", 15) → "ミズホ          "(15桁)
    static String spacePad(String value, int length) {
        return ("%-" + length + "s").formatted(value);
    }

    // ── ヘッダレコード(レコード区分: 1)120バイト ─────────
    // 全銀仕様書「ヘッダ・レコード」に対応
    // ファイル先頭に必ず1件。委託者情報と仕向銀行情報を格納する
    static String buildHeader(String clientCode, String clientName,
                               String transferDate, String bankCode,
                               String bankName, String branchCode,
                               String branchName) {
        var sb = new StringBuilder();
        // [1]     レコード区分 — 1=ヘッダを示す固定値
        sb.append("1");
        // [2-3]   種別コード — 21=総合振込(給与振込は11、口座振替は91)
        sb.append("21");
        // [4]     コード区分 — 0=JIS(半角カナ)、1=EBCDIC
        sb.append("0");
        // [5-14]  委託者コード — 銀行から付番される10桁の識別番号
        sb.append(spacePad(clientCode, 10));
        // [15-54] 委託者名 — 40桁・半角カナ・左詰めスペース埋め
        sb.append(spacePad(clientName, 40));
        // [55-58] 振込指定日 — MMDD形式の4桁(例: 0401=4月1日)
        sb.append(transferDate);
        // [59-62] 仕向銀行番号 — 4桁・ゼロ埋め(例: 0001=みずほ銀行)
        sb.append(zeroPad(Long.parseLong(bankCode), 4));
        // [63-77] 仕向銀行名 — 15桁・半角カナ・スペース埋め
        sb.append(spacePad(bankName, 15));
        // [78-80] 仕向支店番号 — 3桁・ゼロ埋め
        sb.append(zeroPad(Long.parseLong(branchCode), 3));
        // [81-95] 仕向支店名 — 15桁・半角カナ・スペース埋め
        sb.append(spacePad(branchName, 15));
        // [96-120] 予備 — 25桁・スペース埋め(将来の拡張用)
        sb.append(spacePad("", 25));
        return sb.toString();
    }

    // ── データレコード(レコード区分: 2)120バイト ─────────
    // 振込1件につき1レコード。振込先の銀行・口座・金額を格納する
    static String buildDataRecord(TransferData data) {
        var sb = new StringBuilder();
        // [1]     レコード区分 — 2=データを示す固定値
        sb.append("2");
        // [2-5]   振込先銀行番号 — 金融機関コード4桁・ゼロ埋め
        sb.append(zeroPad(Long.parseLong(data.bankCode()), 4));
        // [6-20]  振込先銀行名 — 15桁・半角カナ・スペース埋め
        sb.append(spacePad(data.bankName(), 15));
        // [21-23] 振込先支店番号 — 支店コード3桁・ゼロ埋め
        sb.append(zeroPad(Long.parseLong(data.branchCode()), 3));
        // [24-38] 振込先支店名 — 15桁・半角カナ・スペース埋め
        sb.append(spacePad(data.branchName(), 15));
        // [39-42] 手形交換所番号 — 振込の場合は0000固定
        sb.append("0000");
        // [43]    預金種目 — 1=普通預金, 2=当座預金, 4=貯蓄預金
        sb.append(data.accountType());
        // [44-50] 口座番号 — 7桁・ゼロ埋め
        sb.append(zeroPad(Long.parseLong(data.accountNumber()), 7));
        // [51-80] 受取人名 — 30桁・半角カナ・スペース埋め
        //         法人は「カ)」「ユ)」等の略称記号を先頭に付ける
        sb.append(spacePad(data.accountHolder(), 30));
        // [81-90] 振込金額 — 10桁・ゼロ埋め(最大9,999,999,999円)
        sb.append(zeroPad(data.amount(), 10));
        // [91]    新規コード — 0=その他, 1=第1回振込, 2=変更
        sb.append("0");
        // [92-120] 予備 — 29桁・スペース埋め
        sb.append(spacePad("", 29));
        return sb.toString();
    }

    // ── トレーラレコード(レコード区分: 8)120バイト ────────
    // データレコードの合計件数と合計金額を格納する
    // 銀行側はこの値とデータレコードの実値を突き合わせて整合性を検証する
    static String buildTrailer(int totalCount, long totalAmount) {
        var sb = new StringBuilder();
        // [1]     レコード区分 — 8=トレーラを示す固定値
        sb.append("8");
        // [2-7]   合計件数 — データレコードの件数(6桁・ゼロ埋め)
        sb.append(zeroPad(totalCount, 6));
        // [8-19]  合計金額 — 全データレコードの振込金額合計(12桁・ゼロ埋め)
        sb.append(zeroPad(totalAmount, 12));
        // [20-120] 予備 — 101桁・スペース埋め
        sb.append(spacePad("", 101));
        return sb.toString();
    }

    // ── エンドレコード(レコード区分: 9)120バイト ──────────
    // ファイルの終端を示す。レコード区分以外はすべてスペース埋め
    static String buildEnd() {
        var sb = new StringBuilder();
        // [1]     レコード区分 — 9=エンドを示す固定値
        sb.append("9");
        // [2-120] 予備 — 119桁・スペース埋め
        sb.append(spacePad("", 119));
        return sb.toString();
    }

    // ── バイト長検証 ─────────────────────────────────────────
    // 全レコードが120バイトであることを Shift_JIS ベースで検証する
    static void validateByteLength(String record, String label) {
        var byteLen = record.getBytes(SHIFT_JIS).length;
        if (byteLen != 120) {
            throw new IllegalStateException(
                "%s のバイト長が不正です: expected=120, actual=%d".formatted(label, byteLen));
        }
    }

    public static void main(String[] args) {
        // 振込データを準備(2件の総合振込)
        var transfers = List.of(
            new TransferData(
                "0001", "ミズホ", "001", "ホンテン",
                "1", "1234567", "カ)ヤマダシヨウテン", 1500000L
            ),
            new TransferData(
                "0009", "ミツビシUFJ", "002", "マルノウチ",
                "1", "7654321", "サトウタロウ", 280000L
            )
        );

        // ── ファイル全体を組み立て ────────────────────────
        var lines = new ArrayList<String>();

        // (1) ヘッダレコード — ファイル先頭に1件
        var header = buildHeader(
            "1234567890", "カ)サンプルキギヨウ",
            "0401", "0001", "ミズホ", "001", "ホンテン"
        );
        validateByteLength(header, "ヘッダ");
        lines.add(header);

        // (2) データレコード — 振込1件につき1行
        var totalAmount = 0L;
        for (var td : transfers) {
            var dataLine = buildDataRecord(td);
            validateByteLength(dataLine, "データ");
            lines.add(dataLine);
            totalAmount += td.amount();
        }

        // (3) トレーラレコード — 件数・金額の合計で整合性を担保
        var trailer = buildTrailer(transfers.size(), totalAmount);
        validateByteLength(trailer, "トレーラ");
        lines.add(trailer);

        // (4) エンドレコード — ファイル終端
        var end = buildEnd();
        validateByteLength(end, "エンド");
        lines.add(end);

        // 結果を出力(各行120バイト)
        for (var line : lines) {
            System.out.println("(%3d bytes) %s".formatted(
                line.getBytes(SHIFT_JIS).length, line));
        }
    }
}

Java 8 / 17 / 21 の完全なサンプルコードは GitHub リポジトリ で確認できます。

Version Coverage

record で振込データを簡潔に定義できる。var による型推論と String.formatted() で記述量が大幅に減る。テキストブロックはバイナリフォーマットでは使わないが、テスト用の期待値記述には有用。

Java 17
// Java 17: record + var + formatted() で簡潔に記述
record TransferData(
    String bankCode,       // 振込先銀行番号(4桁)
    String accountHolder,  // 受取人名(30桁・半角カナ)
    long amount            // 振込金額(10桁)
) {}
var line = "2"
    + "%04d".formatted(Long.parseLong(data.bankCode()))
    + "%-30s".formatted(data.accountHolder())
    + "%010d".formatted(data.amount());

Library Comparison

Pure Java(StringBuilder + String.format)全銀フォーマットのようにフィールド定義が仕様書で厳密に決まっている場合。レコード種別が4種と少なく、外部依存を増やしたくないとき。フィールド位置・桁数を手動で管理するため、仕様変更時に修正箇所が分散しやすい。テストコードでバイト長を検証する運用が必須になる。
Fixedformat4jアノテーションベースでフィールド定義と Java オブジェクトのマッピングを自動化したい場合。複数の固定長フォーマットを扱うプロジェクトで統一したいとき。全銀フォーマット固有のルール(半角カナ、レコード区分による構造切替)はカスタムコンバータの実装が必要。ライブラリのメンテナンス状況も要確認。
自前のフィールド定義テーブル(Map/List で桁数・パディングを管理)全銀以外にも EDI やメインフレーム連携の固定長フォーマットが複数ある場合。フィールド定義を外部ファイル化して仕様変更に柔軟に対応したいとき。フレームワーク的な実装が必要で初期構築コストが上がる。小規模なら Pure Java の直書きで十分なことが多い。

注意点

全レコードは120バイト固定長でなければならない。半角カナ(JIS X 0201)はShift_JISで1バイトだが、全角文字が混入すると2バイトになりレコード長がずれる。生成後に getBytes("Shift_JIS").length で必ず120バイトを検証すること。

受取人名や銀行名は半角カナで記述する。濁点(゙)・半濁点(゚)は独立した1バイト文字としてカウントされるため、「バ」は2バイト(ハ+゙)になる。文字数とバイト数を混同しないこと。

トレーラの合計件数・合計金額がデータレコードの実値と一致しないと、銀行側で受付エラーになる。生成処理で必ず集計値を検証するステップを入れること。

振込指定日(MMDD)が銀行の営業日でない場合、翌営業日扱いになるか受付拒否になるかは銀行の運用による。事前に営業日カレンダーとの突き合わせが必要。

改行コードは銀行によって CRLF(Windows)または LF(Unix)の指定が異なる。仕様書に記載がない場合は銀行に確認すること。改行コードの不一致で受付エラーになるケースは多い。

FAQ

全銀フォーマットのレコード長が120バイトにならない場合、どこを確認すべきですか。

半角カナの濁点・半濁点が独立1バイトとしてカウントされているか、全角文字が混入していないかを確認します。生成後に getBytes("Shift_JIS").length で各レコードのバイト長を検証するテストを入れるのが確実です。

テスト環境で全銀データの受入テストをするにはどうすればよいですか。

ダミーの銀行コード・口座番号で全銀ファイルを生成し、銀行が提供するフォーマットチェックツールやファームバンキングのテスト機能で検証します。本番の口座番号は絶対に使わないでください。

総合振込以外(給与振込・口座振替)の全銀フォーマットも同じ構造ですか。

基本のヘッダ・データ・トレーラ・エンドの4構成は共通ですが、種別コード(ヘッダ2-3桁目)やデータレコードのフィールド配置が異なります。種別ごとに全銀仕様書を確認してフィールド定義を切り替えてください。

関連書籍

この記事のテーマをさらに深く学びたい方へ。

※ Amazon アソシエイトリンクを含みます