Java Tips | 文字列処理:半角→全角

Java Java
スポンサーリンク

半角→全角は「機械っぽい文字を“日本語の紙”に合わせる」技

全角→半角は「検索や比較のために揃える」話でしたが、
半角→全角はどちらかというと「見た目・帳票・印刷物の世界」に寄ったニーズが多いです。

例えば、こんな場面です。
帳票やPDFで「数字や記号も含めて“きれいな全角”で揃えたい。
画面上の入力は半角でいいけれど、出力だけは全角で出したい。
外部システムとの連携仕様で『英数字は全角で送ること』と決められている。

こういうときに使うのが 半角→全角ユーティリティ です。
全角→半角と対になる処理ですが、「どこまで全角にするか」の設計が少し違います。


まずは「何を半角→全角にしたいか」を決める

全角にしたい対象をはっきりさせる

よく対象になるのは、だいたいこのあたりです。

数字:0〜90〜9
英字:A〜Z a〜zA〜Z a〜z
記号:!#$%&()=~...!#$%&()=~…
スペース:半角スペース → 全角スペース

カタカナ(半角カタカナ→全角カタカナ)は別テーマとして扱うことが多いので、
ここでは「英数字・記号・スペース」を中心にします。

重要なのは、「全部を全角にするのか、一部だけなのか」を用途ごとに決めることです。
帳票用なら「英数字・記号・スペースすべて全角」、
外部IF用なら「数字だけ全角」など、要件に合わせて変わります。


シンプルな実装:自前マッピングで半角→全角

全角→半角の逆をやるだけ…ではない

全角→半角のときは「`’!’〜’~’ を 0xFEE0 ずらす」というトリック」が使えました。
半角→全角も、基本的にはその逆です。

ただし、半角側は「連続した範囲にきれいに並んでいない記号」もあるので、
実務的には「英数字+よく使う記号+スペース」を自前でマッピングするのが分かりやすいです。

まずは、英数字とスペースだけを対象にしたシンプル版から。

public final class HankakuConverter {

    private HankakuConverter() {}

    public static String toZenkakuAscii(String text) {
        if (text == null || text.isEmpty()) {
            return text;
        }
        StringBuilder sb = new StringBuilder(text.length());
        for (int i = 0; i < text.length(); i++) {
            char ch = text.charAt(i);
            if (ch == ' ') {
                // 半角スペース → 全角スペース
                ch = ' ';
            } else if (ch >= 0x21 && ch <= 0x7E) {
                // 半角の「!」〜「~」を全角に寄せる
                ch = (char) (ch + 0xFEE0);
            }
            sb.append(ch);
        }
        return sb.toString();
    }
}
Java

使い方はこうです。

String s = "Hello! 123 ABC xyz";
String converted = HankakuConverter.toZenkakuAscii(s);
System.out.println(converted);
// Hello! 123 ABC xyz
Java

ここで深掘りしたい重要ポイントは二つです。

一つ目は、「半角の !~(0x21〜0x7E)に 0xFEE0 を足すと、対応する全角記号・英数字になる」という性質を使っていることです。
全角→半角のときは -0xFEE0、半角→全角のときは +0xFEE0、と覚えておくとスッキリします。

二つ目は、「半角スペースだけは範囲外なので、個別に ' ' → ' ' と変換している」ことです。
帳票やPDFで「見た目を揃えたい」とき、スペースが半角のままだと妙に詰まって見えるので、
半角→全角ユーティリティでは真っ先に対応しておくべき存在です。


例題:帳票出力用に「英数字を全角に揃える」

画面入力は半角でOK、出力だけ全角にする

よくあるのが、「画面では半角入力でいいけれど、帳票やPDFでは全角で揃えたい」という要件です。

例えば、請求書の「お客様番号」や「郵便番号」を全角で出したいケース。

public final class ReportFormatter {

    private ReportFormatter() {}

    public static String toZenkakuForReport(String value) {
        if (value == null) {
            return "";
        }
        // 英数字・記号・スペースを全角に
        String zenkaku = HankakuConverter.toZenkakuAscii(value);
        // 必要ならここで桁揃えやパディングも行う
        return zenkaku;
    }
}
Java

使い方はこうです。

String customerNo = "A12345";
String printed = ReportFormatter.toZenkakuForReport(customerNo);
System.out.println(printed);
// A12345
Java

ここでのポイントは、「“帳票用の見た目”という文脈をユーティリティ名に刻んでいる」ことです。
toZenkakuForReport と名前をつけることで、「これは帳票出力のための全角変換なんだな」と一目で分かります。

半角→全角は、全角→半角と違って「検索・比較」よりも「見た目・レイアウト」の話になりやすいので、
どの場面で使うのか(帳票・メール・外部IFなど)をメソッド名で表現しておくと、後から読んだときに迷いません。


Java 標準 Normalizer との関係

NFKC は「半角→全角」ではなく「むしろ全角→半角寄り」

全角→半角のときに紹介した Normalizer.normalize(..., Normalizer.Form.NFKC) は、
「互換文字を標準形に寄せる」方向の変換でした。

NFKC は、

  • 全角英数字 → 半角英数字
  • 丸付き数字 → 通常の数字
  • ローマ数字 → 通常のアルファベット

といった変換を行うので、「半角→全角」には基本的に向きません。

つまり、「半角→全角」は自前でやるのが基本です。
「とにかく“見た目が同じもの”を同一視したい」なら NFKC、
「見た目を“全角に揃えたい”」なら自前マッピング、という住み分けになります。


例題:外部システム連携で「数字だけ全角にする」

仕様で「数字は全角」と決められているケース

たとえば、古いホスト系システムやレガシーな外部IFで、
「数字は全角で送ること」という仕様が残っていることがあります。

この場合、「数字だけ全角にする」ユーティリティを用意しておくと安全です。

public final class HankakuConverter {

    private HankakuConverter() {}

    public static String toZenkakuDigitsOnly(String text) {
        if (text == null || text.isEmpty()) {
            return text;
        }
        StringBuilder sb = new StringBuilder(text.length());
        for (int i = 0; i < text.length(); i++) {
            char ch = text.charAt(i);
            if (ch >= '0' && ch <= '9') {
                ch = (char) (ch + 0xFEE0); // 0〜9へ
            }
            sb.append(ch);
        }
        return sb.toString();
    }
}
Java

使い方はこうです。

String payload = "ID=12345, CODE=A01";
String converted = HankakuConverter.toZenkakuDigitsOnly(payload);
System.out.println(converted);
// ID=12345, CODE=A01
Java

ここで深掘りしたいのは、「“何を全角にするか”をメソッドごとに分けている」ことです。
toZenkakuAscii は英数字・記号・スペース全部、
toZenkakuDigitsOnly は数字だけ、といった具合に分けておくと、
呼び出し側が「この変換はどこまでやるのか」を直感的に理解できます。


まとめ:半角→全角ユーティリティで身につけたい感覚

半角→全角は、「機械っぽい半角文字を、日本語の紙や帳票の世界に合わせて整える」ための技です。

押さえておきたい感覚は、まず「半角の !~ に 0xFEE0 を足すと、対応する全角英数字・記号になる」という事実。
次に、「半角スペースは個別に ' ' → ' ' と変換しないと、レイアウトが崩れたり見た目が揃わなかったりする」ということ。
そして、「帳票用・外部IF用など、文脈ごとに“どこまで全角にするか”を決め、そのルールをユーティリティクラスに閉じ込めてプロジェクト全体で共有する」ことです。

もしあなたのコードのどこかに、「出力直前に replace(' ', ' ') したり、数字だけ手作業で全角にしている」箇所があるなら、
それを題材にして、ここで作った HankakuConverterReportFormatter のようなユーティリティにまとめてみてください。
それだけで、「見た目が揃って、仕様変更にも強い文字列出力」に、一段レベルアップできます。

タイトルとURLをコピーしました