Javaで、文字列中に含まれる「全角数字(0〜9)」だけを「半角数字(0〜9)」へ変換したい場面はよくあります。
-
ユーザーが全角で入力してくるフォームの値を内部では半角で扱いたい
-
CSVやログ出力は半角数字で揃えたい
-
既存システムから移行したデータに全角数字が混在している
ここでは、Unicodeの仕組みを利用して「全角数字だけを半角数字に変換するメソッド」と、その動作を確認するJUnitテストのサンプルをまとめます。
全角数字と半角数字の関係
Unicodeでは、全角数字と半角数字は次のような関係になっています。
-
全角数字 0〜9:
0xFF10〜0xFF19 -
半角数字 0〜9 :
0x0030〜0x0039
両者には常に「0xFEE0」という一定の差があります。
つまり、文字列中の1文字ずつを見て
-
文字コードが
0xFF10〜0xFF19の範囲に入っていれば全角数字 -
その場合は
char - 0xFEE0で半角数字に変換
というロジックで処理できます。
サンプル1:全角数字を半角数字に変換するメソッド
まずはシンプルなユーティリティメソッドの例です。
ポイント
-
null が渡された場合はそのまま null を返す
-
StringBuilder を使ってインプレースで書き換える
-
判定しているのは全角数字の範囲のみなので、英字や記号、日本語などはそのまま残る
動作例
上記メソッドの動作イメージです。
フォーム入力値やファイル入力値にそのまま適用して、数字だけ半角に統一することができます。
サンプル2:ストリームAPI(codePoints)を使った書き方
Java 8 以降なら、String#codePoints() を使って書くこともできます。
ループを書かなくて済むぶん、処理の意図が読みやすくなる場合もあります。
一方で、文字列長がとても短いケースが中心であれば、先ほどの for 文のほうが素直に感じられるかもしれません。
JUnitで動作を確認する
次に、上記メソッドの動作を確認するための JUnit テスト例です。
ここでは JUnit 5 を前提とします。
テストのポイント
-
シンプルなケース(全角数字のみ)
-
他の文字と混在しているケース
-
数字を含まないケース
-
null を渡したケース
をそれぞれ分けて確認しておくと、後から仕様変更した時でも安心です。
ついでに:全角数字が含まれているかだけチェックするメソッド
入力チェックの段階で「全角数字が含まれているかどうか」だけを知りたい場合は、次のようなヘルパーメソッドを用意しておくと便利です。
このメソッドでチェックして、必要であれば changeNumFullToHalf を呼ぶ、という形にしておくと、
「変換が必須の項目」と「警告だけ出したい項目」で処理を分けやすくなります。
まとめ
-
Unicode では、全角数字(0〜9)と半角数字(0〜9)は一定値(0xFEE0)の差で並んでいる
-
文字コードを見て
0xFF10〜0xFF19の範囲なら全角数字とみなし、- 0xFEE0で半角に変換できる -
StringBuilder を使ったループ実装と、
codePoints()を使ったストリーム実装の両方が書ける -
JUnit で代表的なパターンをテストしておくと、後から仕様を変えたときも安全
フォーム入力の整形や、CSV・ログ出力のフォーマット統一などで、全角数字→半角数字の変換はよく使う処理なので、
共通ユーティリティクラスにひとつ用意しておくと再利用しやすくなります。
