概要
固定長フォーマットとは、各フィールドが仕様書で決められたバイト数を占め、短い場合はスペースやゼロで埋めるデータ交換形式です。CSV のようにデリミタで区切る可変長形式と異なり、バイト位置だけでフィールドを特定できるため、汎用機・ホストコンピュータとのデータ連携で長く使われてきました。全銀フォーマットもこの固定長形式を採用しており、すべてのレコードが120バイト固定長である点が最大の特徴です。フォーマットはヘッダ(レコード区分1)、データ(区分2)、トレーラ(区分8)、エンド(区分9)の4種別で構成され、文字コードは JIS X 0201(半角カナ・英数字)、エンコーディングには Shift_JIS を使用します。数値フィールドは右詰めゼロ埋め、文字フィールドは左詰めスペース埋めという規則があり、1バイトでもずれると銀行側で受付エラーになります。ただし、全銀協の標準仕様はあくまで共通の骨格です。使用可能な文字セットの細部、データレコードの振込区分・EDI情報フィールドの値、レコード間の改行コードの有無など、実装上の重要な挙動は銀行ごとに異なります。特に新規コード対応以降は銀行が個別に要求する内容が増えており、実装前に必ず対象銀行のフォーマット仕様書を入手することが前提です。全銀仕様書に基づいたレコード生成処理を Pure Java で実装し、フィールドごとのバイト長・パディング規則・よくある実装ミスを整理した。トレーラの合計件数・合計金額によるデータ整合性チェックの仕組みも含め、実務でそのまま使える形に仕上げている。
使いどころ
月次の総合振込データを基幹システムから生成し、銀行のファームバンキングへ送信する
給与振込バッチで従業員の口座情報と支給額を全銀フォーマットに変換する
取引先への支払データを経理システムから全銀形式でエクスポートする
口座振替の請求データを全銀フォーマットで作成し、収納代行サービスへ連携する
テスト環境で全銀データのダミーファイルを生成し、受入テストに使用する
コード例
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
/**
* 全銀フォーマット(総合振込)のレコード生成サンプル。
*
* ■ 固定長フォーマットとは
* 各フィールドが仕様書で決められたバイト数を占め、短い場合はスペース/ゼロで埋める
* データ形式。バイト位置でフィールドを特定するため、区切り文字がない。
*
* ■ レコード構成(全種別120バイト固定長)
* ヘッダ (レコード区分: 1)— ファイル先頭に1件。委託者情報・仕向銀行を格納。
* データ (レコード区分: 2)— 振込1件につき1レコード。振込先・金額を格納。
* トレーラ(レコード区分: 8)— 合計件数・合計金額。銀行側が整合性チェックに使用。
* エンド (レコード区分: 9)— ファイル終端を示す。1+119スペースのみ。
*
* ■ パディング規則
* 数値フィールド → 右詰め・前ゼロ埋め(例: 金額 1500000 → "0001500000")
* 文字フィールド → 左詰め・後ろスペース埋め(例: 銀行名 "ミズホ" → "ミズホ ")
*
* ■ 文字コード
* JIS X 0201(半角カナ・英数字・一部記号)、Shift_JIS エンコーディング
* ※ 使用可能文字の細部(記号の可否等)は銀行によって異なる
*
* ■ 改行コードについて
* CRLF を含めて受け付ける銀行、LF のみ、改行なし(純粋な固定長連結)がある。
* 対象銀行のフォーマット仕様書で必ず確認すること。
*
* ⚠ 実装前に対象銀行のフォーマット仕様書を入手すること。
* 特にデータレコードの予備領域(91桁以降)は銀行独自の利用がある場合がある。
*/
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桁(標準はスペース埋め)
// ⚠ 銀行によってはここにEDI情報(振込付帯情報)や独自フィールドを設定する。
// 特に新規コード対応以降、この領域の使い方は銀行ごとに異なる。
// 対象銀行のフォーマット仕様書を必ず確認すること。
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バイト(ハ+゙)になる。文字数とバイト数を混同しないこと。
使用可能な文字セットは銀行によって異なる。全銀協標準では半角カナ・英大文字・数字・一部の半角記号(スペース、括弧、ハイフン、スラッシュ等)を認めているが、特定記号の可否や法人略称記号(カ)、ユ)等)の扱いは銀行の個別仕様で制限・拡張される場合がある。対象銀行のフォーマット仕様書で許容文字を必ず確認すること。
データレコードの振込区分フィールドやEDI情報(振込付帯情報)は、銀行・ファームバンキングサービスによって独自の設定値や追加フィールドを要求するケースがある。特に新規コード(データ91桁目)以降の予備領域は、一部の銀行が独自情報の格納に使用している。標準仕様書だけを参照して実装すると受付エラーになる場合があるため、必ず対象銀行のフォーマット仕様書を入手して確認すること。
トレーラの合計件数・合計金額がデータレコードの実値と一致しないと、銀行側で受付エラーになる。生成処理で必ず集計値を検証するステップを入れること。
振込指定日(MMDD)が銀行の営業日でない場合、翌営業日扱いになるか受付拒否になるかは銀行の運用による。事前に営業日カレンダーとの突き合わせが必要。
レコード間の改行コードの扱いは銀行によって3パターンある。①CRLF(\r\n)を含めて受け付ける、②LFのみを受け付ける、③改行コードなし(120バイト×レコード数の純粋な固定長連結)を要求する。仕様書に記載がない場合は必ず銀行に確認すること。改行コードの不一致は受付エラーの典型的な原因のひとつ。
FAQ
半角カナの濁点・半濁点が独立1バイトとしてカウントされているか、全角文字が混入していないかを確認します。生成後に getBytes("Shift_JIS").length で各レコードのバイト長を検証するテストを入れるのが確実です。
銀行によって異なります。CRLFを含めて受け付ける銀行、LFのみの銀行、改行コードなし(純粋な固定長連結)を要求する銀行があります。仕様書に記載がなければ銀行担当者に確認してください。誤った改行コードは受付エラーの原因になります。
標準仕様ではスペース埋めですが、一部の銀行はEDI情報(振込付帯情報)や独自の振込区分を予備領域に格納するよう要求します。新規コード対応後は銀行ごとの個別要件が増えているため、必ず対象銀行のフォーマット仕様書を確認してください。
ダミーの銀行コード・口座番号で全銀ファイルを生成し、銀行が提供するフォーマットチェックツールやファームバンキングのテスト機能で検証します。本番の口座番号は絶対に使わないでください。
基本のヘッダ・データ・トレーラ・エンドの4構成は共通ですが、種別コード(ヘッダ2-3桁目)やデータレコードのフィールド配置が異なります。種別ごとに全銀仕様書を確認してフィールド定義を切り替えてください。