概要
全銀フォーマットは、全国銀行協会連合会(全銀協)が定めた銀行間データ交換の標準フォーマットです。総合振込、給与振込、口座振替など、企業が銀行へ振込データを送る際に広く使われており、多くの業務システムで生成処理が求められます。フォーマットはヘッダ(レコード区分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));
}
}
}Version Coverage
record で振込データを簡潔に定義できる。var による型推論と String.formatted() で記述量が大幅に減る。テキストブロックはバイナリフォーマットでは使わないが、テスト用の期待値記述には有用。
// 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
注意点
全レコードは120バイト固定長でなければならない。半角カナ(JIS X 0201)はShift_JISで1バイトだが、全角文字が混入すると2バイトになりレコード長がずれる。生成後に getBytes("Shift_JIS").length で必ず120バイトを検証すること。
受取人名や銀行名は半角カナで記述する。濁点(゙)・半濁点(゚)は独立した1バイト文字としてカウントされるため、「バ」は2バイト(ハ+゙)になる。文字数とバイト数を混同しないこと。
トレーラの合計件数・合計金額がデータレコードの実値と一致しないと、銀行側で受付エラーになる。生成処理で必ず集計値を検証するステップを入れること。
振込指定日(MMDD)が銀行の営業日でない場合、翌営業日扱いになるか受付拒否になるかは銀行の運用による。事前に営業日カレンダーとの突き合わせが必要。
改行コードは銀行によって CRLF(Windows)または LF(Unix)の指定が異なる。仕様書に記載がない場合は銀行に確認すること。改行コードの不一致で受付エラーになるケースは多い。
FAQ
半角カナの濁点・半濁点が独立1バイトとしてカウントされているか、全角文字が混入していないかを確認します。生成後に getBytes("Shift_JIS").length で各レコードのバイト長を検証するテストを入れるのが確実です。
ダミーの銀行コード・口座番号で全銀ファイルを生成し、銀行が提供するフォーマットチェックツールやファームバンキングのテスト機能で検証します。本番の口座番号は絶対に使わないでください。
基本のヘッダ・データ・トレーラ・エンドの4構成は共通ですが、種別コード(ヘッダ2-3桁目)やデータレコードのフィールド配置が異なります。種別ごとに全銀仕様書を確認してフィールド定義を切り替えてください。