文字コード これだけは覚えておこう ~シフトJIS編~
はじめに
#日頃、Javaの初心者からベテランまで様々なスキルレベルの方から質問を頂く立場で仕事しておりますが、Java言語を使用するうえで基本事項でありながらも、あまり理解されていない事柄があると感じています。これらの事柄については改めて誰かに質問できず、「そういうもの」として無理やり納得しやり過ごしている方がいるのではないでしょうか。ここではそのような事柄について改めて解説し、その理由を知ることで「だからこうするべき」、「だからこれはダメ」ということを理解する手助けになればと考えます。
今回は「新人向け」というテーマをもらったので、プログラマーなら避けて通れない「文字コード」、特に「シフトJIS」についてこれだけは知っておいて欲しいポイントを解説します。
今回言いたいポイント
#- 「シフトJIS」には気をつけろ
事例
#文字コードに関する相談で多いのが「文字化け」です。以下の事例をベースに文字化けの原因と対策を見ていきましょう。
相談事例
#「シフトJISでファイル出力したのですが文字化けしてしまいました。どうしたらよいですか」という相談。
コードは以下のようなもの。
/**
* 顧客情報をCSV形式でファイルに出力する。
*
* @param customers 顧客情報
* @param filePath 出力ファイルパス
* @throws IOException ファイル出力エラー
*/
public static void writeToFile(List<Customer> customers, String filePath) throws IOException {
try (PrintWriter writer = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(new FileOutputStream(filePath), Charset.forName("Shift_JIS"))))) {
for (Customer customer : customers) {
writer.println(toCsvData(customer));
}
}
}
これで出力したところ、会社名に含まれていた「㈱」や「髙(はしご高)」が「?」で出力されてしまったという事象です。
文字コードとは
#文字コードとは、特定の文字に対して一意の番号(数値)を割り当てる規則です。この数値は、コンピュータが文字を識別し、処理するために使用されます。
また、その規則が適用される文字を文字集合(キャラクターセット)、文字コードをバイト列に変換する方法をエンコードとよびます。
とはいえ、文字コードとエンコードはほぼ同意に用いられることが多いので、あまり厳密にとらえる必要はありません。
なお、JavaのCharset
は文字集合とエンコードの組み合わせとして定義されています。
Shift_JISとMS932
#では、Shift_JISとはどのようなものでしょうか。
文字集合としてはJIS X 0201で規定される文字(半角英数字と半角カタカナ)とJIS X 0208で規定される文字(全角ひらがな、全角カタカナ、第1・第2水準漢字など)を合わせたものです。
一方、Windows上で一般にシフトJISとして扱われるのは、MS932(=Windows-31J)と呼ばれるものです。これはShift_JISにIBM拡張文字、NEC選定IBM拡張文字、およびNEC特殊文字を加えたものです。
これらの文字は、Shift_JISには無いが便利なため、IBMやNECといったベンダーが独自に拡張した文字集合です。
「①(丸付き数字)」やローマ数字、第3・第4水準漢字の一部、今回文字化けしてしまった「㈱」や「髙(はしご高)」もこれに含まれます。
解決
#一見問題の無いコードに見えますが、問題はCharset
に指定しているShift_JISです。シフトJISでファイル出力したいのだからShift_JISを指定するのは当然のように思われるかもしれませんが、これが罠です。ある程度経験を積んだ方なら当然の事項であり暗黙知となっていますので、経験の浅い方には説明されないことがあります。
今回は出力する文字に「㈱」や「髙(はしご高)」といったShift_JISでは扱えない文字がありましたので、これが「?」に変換されてしまい文字化けとなっています。
これらの文字も正しく出力したいのであれば、MS932を使用する必要があります。
一方で、「シフトJISで出力する」という要件について、Shift_JISとMS932の違いを再確認する必要があります。例えば、ファイルを提供する先のシステムがShift_JISとして読み込む場合、MS932で保存されたファイルには読み込めない文字が含まれている可能性があり、これがエラーの原因になることがあります。
要件定義者が「シフトJIS」という言葉の意味を正確に理解していない場合もあります(Shift_JISとMS932の違いが曖昧で、同一視していることもあります)。
そのため、「㈱」や「①」、「髙(はしご高)」などの特定の文字が含まれている場合に問題がないか、具体的な文字を示して確認することが重要です。
まとめ
#- Shift_JISとMS932はどちらも一般に「シフトJIS」と呼ばれることがあります。
- Shift_JISとMS932は扱える文字に違いがあります(Shift_JIS ⊂ MS932)。
- 要件を確認し、正しいCharsetを指定する必要があります。