プログラミング

Java 全角 半角 変換の実装方法:Normalizerとコードポイントを比較

公開日: |読了時間: 約9分 |対象: Java開発者・データ整形

Java 全角 半角 変換は、すべてを一括で正規化したいのか、全角英数字だけを限定して変換したいのかで実装が変わります。この記事では、Normalizer.Form.NFKC とコードポイントの明示変換を比較し、入力仕様に合った選び方、テスト、運用上の注意点を整理します。

Javaで全角英数字を半角へ変換する入力と出力の比較図
全角英数字を半角へ変換する場合でも、対象範囲を先に決めると意図しない文字変化を防げます。

Java 全角 半角 変換は方法を使い分ける

結論から言うと、フォーム値や検索キーの表記ゆれを広くそろえるならNFKC、データベースの列で全角ASCIIだけを半角にしたいならコードポイントの明示変換が扱いやすいです。前者は便利な一方、互換文字や半角カタカナまで変わるため、変換後の期待値を決めずに導入すると別の不具合を招きます。

方法向いている用途注意点
Normalizer.NFKC入力の互換表現をまとめて正規化半角カタカナ、丸数字なども変化する
コードポイント変換全角英数字・全角スペースだけを変換記号やカナを変えない仕様を自分で定義する
変換しない原文保存、監査ログ、表示用テキスト検索・照合用の正規化値を別列で持つ
実務の基準:原文を上書きする前に、入力値・正規化値・表示値の役割を分けます。変換処理は「何を変え、何を残すか」が仕様そのものです。

Normalizer(NFKC)でまとめて正規化する

java.text.Normalizer はUnicodeの正規化を行う標準APIです。Form.NFKC を使うと、全角の英字・数字・一部記号を通常のASCII表現へ寄せられます。短い入力や、互換表現を同じ検索キーとして扱いたい場面では実装が簡潔です。

import java.text.Normalizer;

public static String normalizeWidth(String text) {
    if (text == null) {
        return null;
    }
    return Normalizer.normalize(text, Normalizer.Form.NFKC);
}

// ABC123 → ABC123 

この方法のポイントは「半角にするAPI」ではなく「互換文字を正規化するAPI」だということです。たとえば半角カタカナのアイウは全角カタカナのアイウに寄る場合があります。丸数字、単位記号、合字なども入力に含まれるなら、変換前後の差分をテストで確認してください。

また、NFKCを使って半角ASCIIを全角へ戻すことはできません。NFKCは正規化の方向が決まっており、半角を全角表示へ変換する逆処理ではないためです。帳票の桁位置をそろえるなど、半角から全角へ変換する場合は、次の明示変換を検討します。

Javaの全角半角変換を入力、変換、期待値確認の3段階で進めるフロー図
入力の種類、選んだ変換方式、期待値の3段階を確認すると、正規化の範囲をレビューしやすくなります。

コードポイントを限定して変換する

全角ASCII(U+FF01〜U+FF5E)と全角スペース(U+3000)だけを半角にしたい場合は、変換対象を条件分岐で明示できます。全角ASCIIと半角ASCIIの差は16進数で0xFEE0なので、コードポイント単位で処理します。

public static String toHalfWidthAscii(String text) {
    if (text == null) {
        return null;
    }

    StringBuilder result = new StringBuilder(text.length());
    text.codePoints().forEach(codePoint -> {
        if (codePoint == 0x3000) {
            result.append(' ');
        } else if (codePoint >= 0xFF01 && codePoint <= 0xFF5E) {
            result.appendCodePoint(codePoint - 0xFEE0);
        } else {
            result.appendCodePoint(codePoint);
        }
    });
    return result.toString();
}

text.codePoints()appendCodePoint() を使うと、BMP外の絵文字などをUTF-16のchar一つとして誤って分割しません。日本語、改行、絵文字、半角カタカナは対象外のまま保持できるため、「英数字とスペースだけ」の列に向いています。

逆方向の半角から全角は、ASCII範囲(U+0021〜U+007E)に0xFEE0を加え、半角スペースだけをU+3000へ置き換えます。ただし、URL、メールアドレス、コード、IDまで全角化すると利用できなくなるため、表示用や帳票用など範囲を限定して使ってください。

public static String toFullWidthAscii(String text) {
    if (text == null) {
        return null;
    }
    StringBuilder result = new StringBuilder(text.length());
    text.codePoints().forEach(codePoint -> {
        if (codePoint == 0x20) {
            result.appendCodePoint(0x3000);
        } else if (codePoint >= 0x21 && codePoint <= 0x7E) {
            result.appendCodePoint(codePoint + 0xFEE0);
        } else {
            result.appendCodePoint(codePoint);
        }
    });
    return result.toString();
}

変換仕様と入力例を先に決める

実装前に、変換対象と保持対象を表にします。仕様が曖昧なまま「半角化」すると、ユーザーが入力した日本語や記号まで書き換えてしまい、再現性のないデータ修正になります。

入力限定変換の結果NFKCの例
ABC123ABC123ABC123
全角 空白全角 空白全角 空白
アイウそのまま保持アイウになる可能性
日本語😀そのまま保持通常はそのまま
  • nullと空文字:呼び出し側の契約に合わせ、nullを返すか例外にするかを統一します。
  • 改行:行単位で処理する必要がなければ、そのまま保持します。
  • 記号:「全角記号も変換する」のか、英数字だけなのかを明記します。
  • 原文保存:監査や再変換が必要なら、入力値を上書きせず別フィールドへ保存します。

テストと運用の注意点

テストは変換できた例だけでなく、変換してはいけない例も入れます。特に半角カタカナ、全角スペース、絵文字、改行、nullを同じテストセットにすると、NFKCと限定変換の差を確認できます。

assertEquals("ABC123", toHalfWidthAscii("ABC123"));
assertEquals("全角 空白", toHalfWidthAscii("全角 空白"));
assertEquals("アイウ", toHalfWidthAscii("アイウ"));
assertEquals("日本語😀", toHalfWidthAscii("日本語😀"));
assertEquals("アイウ", normalizeWidth("アイウ"));
性能:文字列を一度走査する実装は入力長に比例して処理できます。大量CSVでは、1セルごとのログ出力や不要な中間文字列の生成が時間とメモリを増やすため、バッチ単位の計測とサンプル検証を分けます。
入力の扱い:文字幅変換は入力値の検証やサニタイズの代わりではありません。SQL、HTML、シェル、ログ出力へ渡す前のエスケープやパラメータ化は、変換後も別途必要です。

標準APIの仕様は、Oracle Java APIのNormalizerリファレンスで確認できます。コードポイント処理の考え方は、String.codePoints() の仕様も合わせて読むと、サロゲートペアを含む入力を安全に扱いやすくなります。

用途別の使い分け

短い文字列を確認したい場合は全角半角変換ツール、ASCIIの数値や16進表現まで確認したい場合はASCII変換ツールが便利です。Unicodeのコードポイントやエンコードの基礎は文字コード変換の解説で整理できます。

Javaの実装では、まず変換前後の仕様をテストに固定し、その後にNFKCか限定変換かを選びます。変換方式を後から変更すると検索キーや重複判定の結果が変わるため、仕様書とテストケースを同じ変更単位で管理してください。

Java 全角 半角 変換のよくある質問

Javaで全角英数字だけを半角にするには?

U+FF01〜U+FF5EをU+0021〜U+007Eへ移し、U+3000だけを半角スペースへ変換するコードポイント方式が適しています。半角カタカナや日本語を残したい場合はNFKCより安全に範囲を限定できます。

Normalizerで半角を全角に戻せますか?

NFKCは互換表現を正規化する処理なので、半角ASCIIを全角表示へ戻す逆変換ではありません。帳票などで全角化が必要なら、ASCII範囲とスペースを明示的に変換します。

半角カタカナもJavaで変換されますか?

NFKCでは半角カタカナが全角カタカナへ寄ることがあります。半角カタカナを保持したいときは限定変換を使い、変換したいときはその結果を期待値としてテストに明記します。

絵文字が文字化けしない方法は?

コードポイント単位で処理し、対象外のコードポイントをそのままappendCodePoint()へ渡します。文字幅変換だけでエンコード方式を変えることはできないため、保存時のUTF-8設定も別に確認してください。

まとめ

Java 全角 半角 変換は、互換文字までまとめて整えるならNFKC、全角英数字とスペースだけを変えるならコードポイント方式、と整理できます。入力に半角カタカナ、記号、絵文字、URLが混ざる場合は、変換対象を限定してテストし、原文を残した設計にすると運用しやすくなります。

参考情報

関連記事

プログラミング

ASCII変換プログラミングガイド

JavaScript・Python・Java・C#で文字コードを扱うときの基本を確認できます。

文字コード

Unicode・ASCII・16進数の変換

コードポイントとエンコードの違いを、変換例とともに整理します。

変換ツール

全角半角変換ツール

実際の文字列で全角・半角の変化を確認できます。