プログラマーの常識をJavaで身につける (6)
‘愛’で学ぶ文字コードと文字化けの常識
NTTデータ ビジネスブレインズ
伊賀敏樹
2007/6/21
Javaで文字エンコーディングを使ってみよう
前述のように、Javaは内部的に文字エンコーディングとしてUTF-16を用いています。このUTF-16をほかの文字エンコーディングに変換するための機能がJava APIとして提供されています。世の中にあるさまざまな文字エンコーディングを取り扱うために、この機能は必要になります。
■ バイト配列を16進表記文字列にする便利クラスを差し上げます
まず、バイト配列を一般的な16進表記文字列にするためのユーティリティクラス(HexStringUtil.java)を準備しておきます。
public final class HexStringUtil { |
これ以降のソースコードは、このユーティリティクラスが存在することを前提としています。なお、このようなユーティリティは文字コードを調べる目的以外でも有益である場合があります。ぜひご活用ください。
■ 文字列 → シフトJISのバイト配列
最初に、日本語の文字エンコーディングとしてよく用いられているシフトJISの文字エンコーディングを調べます。Java上の文字列をシフトJISのバイト配列に変換する例を見てみましょう。
|
実行すると、下記のような結果を取得できます。
実行結果 |
[愛植岡]をシフトJISのバイト配列に変換 88 a4 90 41 89 aa |
この例では3文字が6個のbyteへと変換されていることが分かります。ただこれでは、どの文字がどの文字に変換されたのか分からないので、1文字だけ変換してみます。上記ソースコード中の桃色の個所を下記のように書き換えます。
new StringToBytesSample().process("愛"); |
すると、‘愛’の文字が88 a4 という2バイトへと変換されることが分かります。
実行結果 |
[愛]をシフトJISのバイト配列に変換 88 a4 |
■ シフトJISのバイト配列 → 文字列
これとは逆に、バイト配列から文字列を作ることができます。今回得られたバイト配列を下記ソースコード中の桃色の個所のように与えて、文字列へと変換します。
import java.io.UnsupportedEncodingException; |
実行結果は下記のようになります。元の文字列に戻っていることが分かります。
実行結果 |
[88 a4 90 41 89 aa]をシフトJISのバイト配列として文字列に変換 愛植岡 |
文字列とバイト配列の相互変換は、下記のような対応になります。
図3 文字列とバイト配列の相互変換 |
■ それ以外の文字エンコーディングを調べるための事前準備
それでは、シフトJIS以外の文字エンコーディングも調べていきます。まず、簡単に文字エンコーディングを切り替えられるように、先ほどのStringToBytesSample.javaのソースコードを少し拡張し、文字エンコーディング指定を外部から変更できるようにしておきます。
import java.io.UnsupportedEncodingException; |
準備ができたので、サンプルプログラムを動作させてみましょう。私たちはプログラマーなので、こういった事象をプログラムを使って検証できます。
■ EUC-JPエンコーディング
まず、UNIXなどで日本語を扱う際によく使われているEUC-JPエンコーディングを指定して動作させてみます。
new StringToBytesSampleEnc().process("愛植岡", "EUC-JP"); |
実行結果 |
[愛植岡]を[EUC-JP]バイト配列に変換 b0 a6 bf a2 b2 ac |
ここで指定できる文字列は 前述のサポートされているエンコーディングのページで調べることができます。EUC-JP以外にも、よく知られる文字エンコーディングを与えてみましょう。
■ ISO-2022-JPエンコーディングを指定した場合
実行結果 |
[愛植岡]を[ISO-2022-JP]バイト配列に変換 1b 24 42 30 26 3f 22 32 2c 1b 28 42 |
エスケープシーケンスと呼ばれるものが付与されているため、かなりバイト数が増えます。エスケープシーケンスについての詳細は、『文字コード超研究』の316ページなどを参照ください。
■ UTF-8エンコーディングを指定した場合
特に、XMLなどにおいて頻繁に利用されるのが、UTF-8エンコーディングです。UTF-8はUnicodeの文字エンコーディングのひとつです。
実行結果 |
[愛植岡]を[UTF-8]バイト配列に変換 e6 84 9b e6 a4 8d e5 b2 a1 |
■ UTF-16エンコーディングを指定した場合
同じく、XMLなどにおいてよく利用されるのが、UTF-16エンコーディングです。UTF-16はUnicodeの文字エンコーディングのひとつです。
UTF-16エンコーディングはバイト配列表現に変換する際に注意が必要になります。というのも、16ビットであるchar型を8ビットであるbyte型に詰め込む際に、上位8ビットと下位8ビットのいずれのbyteを配列として先に位置させるのか(エンディアン)を明示する必要があるからです。
UTF-16BEはビッグエンディアン(big endian)を明示したUTF-16です。上位8ビットの方が先に配置されます(先ほど‘愛’は611bだったことを思い出してください)。
実行結果 |
[愛植岡]を[UTF-16BE]バイト配列に変換 61 1b 69 0d 5c a1 |
UTF-16LEはリトルエンディアン(little endian)を明示したUTF-16です。下位8ビットの方が先に配置されます。
実行結果 |
[愛植岡]を[UTF-16LE]バイト配列に変換 1b 61 0d 69 a1 5c |
UTF-16はエンディアンを明示していません。その代わり、先頭に「バイト順マーク(BOM:Byte Order Mark)」というものを2バイト付与してエンディアンを表現します。この2バイトでリトルエンディアンかビッグエンディアンかを判断できるようになっています。
実行結果 |
[愛植岡]を[UTF-16]バイト配列に変換 fe ff 61 1b 69 0d 5c a1 |
なお、この実行例はビッグエンディアンです。リトルエンディアンの際には、先頭にff fe の2バイトが付与されます。
■ サポートされていない文字エンコーディングを指定すると例外発生
ここでもし、Javaでサポートされていない文字エンコーディングを指定すると、例外が発生します。例えば、存在しない名称の“ARIMASEN”エンコーディングを指定してみて動作させてください。下記のような例外が発生します。
実行結果 |
[愛植岡]を[ARIMASEN]バイト配列に変換 サポートされないエンコーディング[ARIMASEN]が指定されました。 java.io.UnsupportedEncodingException: ARIMASEN at sun.io.Converters.getConverterClass(Unknown Source) at sun.io.Converters.newConverter(Unknown Source) at sun.io.CharToByteConverter.getConverter(Unknown Source) at java.lang.StringCoding.encode(Unknown Source) at java.lang.String.getBytes(Unknown Source) at StringToBytesSampleEnc.process(StringToBytesSampleEnc.java:18) at StringToBytesSampleEnc.main(StringToBytesSampleEnc.java:6) |
このように、文字エンコーディング名は少しでも間違えると、サポートしないエンコーディング名を指定したことになり、例外が発生します。
2/4 |
Index | ||||||||||
|
プログラマーの常識をJavaで身につける バックナンバー
Java Solution全記事一覧 |
- 技術者が知っておきたいTomcat 7の新機能20連発 (2011/6/24)
6から変わっていない点と併せて、バージョン管理やメモリ管理、セキュリティに関する変更点など厳選して紹介 - いまさら聞けないHadoopとテキストマイニング入門 (2011/6/21)
それぞれの概要や構成、MapReduceの仕組み、Hadoopの活用場面などを解説し、Hadoopの実行環境を構築します - AWSの自由自在なPaaS「Elastic Beanstalk」とは (2011/6/15)
Javaアプリをデプロイ後即起動できる無料クラウドサービスについて特徴やEclipseプラグインの使い方などを紹介。Railsにも対応予定 - Tomcat 7も対応したServlet 3.0の変更点 後編 (2011/6/10)
非同期処理や、認証用APIとセキュリティ制約の追加、JSESSION Cookie、マルチパート対応について解説
|
|
キャリアアップ
スポンサーからのお知らせ
- - PR -
- - PR -