日本語によく使われる文字コード

エディタに適当な文字を書いて様々な文字コードを指定して保存し、どのように記録されているかを調べます。

例にあげる文字列は、

ABCあいうえde 12かきく

です。どの文字コードでも結果は次のように表示されています。

バイトの並び
対応する文字

ISO-2022-JP

1bで始まる特別な文字の並びが来るとUS-ASCIIと解釈するか日本語の文字と解釈するかを切り替えます。

41 42 43 1b 24 42 24 22 24 24 24 26 24 28 1b 28 42 64 65 20 31 32 1b 24 42 24 2b 24 2d 24 2f 1b 28 42 0a
A B C ESC $ B ESC ( B d e 1 2 ESC $ B ESC ( B \n

1b 24 42 がないと、「あいうえ」の部分もUS-ASCIIとして解釈されますので次のようになります。

24 22 24 24 24 26 24 28
$ " $ $ $ & $ (

同様に、「かきく」の部分もUS-ASCIIとして解釈されますので次のようになります。

24 2b 24 2d 24 2f
$ + $ - $ /

ISO-2022-JP は E-メール などで使われています。

Shift_JIS

JIS X 0201 で定義された半角カナ文字も含めて切りかえなして日本の文字を使うために考えられた文字コードです。8ビットコードで1バイト目が8列9列e列f列の時は次の1バイトと合わせて2バイトで日本の文字とするという仕組みです。

切りかえのための余計な文字列がなく、横幅を取る日本の文字が2バイト、横幅が狭くてもよい英数字と半角カナは1バイトなので表示幅も2:1にすれば文字列のバイト数と表示幅が一致しますので便利でした。

当時は半角カナが多く使われていた関係で今までにあるデータを書き直さずに使えるところも互換性もポイントでしたが、半角カナの存在が重要でなくなった現在では狭いところに日本の文字を押し込めた弊害が目立ってきています。

41 42 43 82 a0 82 a2 82 a4 82 a6 64 65 20 31 32 82 a9 82 ab 82 ad 0a
A B C d e 1 2 \n

Shift_JIS の注意点は 0x5c です。WindowsというOSではCドライブの"My Documents"というフォルダの"予定表.doc"というファイルがある場合、半角の \(0x5c) で区切って次のように表します。0x5cは JIS X 0201 に従うと ¥ 、US-ASCII に従うと \ になります。

C:\My Documents\予定表.doc
43 3a 5c 4d 79 20 44 6f 63 75 6d 65 6e 74 73 5c 97 5c 92 e8 95 5c 2e 64 6f 63 0a
C : \ M y D o c u m e n t s \ . d o c \n

Shift_JISを解しないソフトでは次のように見えます。「予」と「定」の中に \ が含まれているのでこれをフォルダやファイル名の区切りと間違ってしまいます。

43 3a 5c 4d 79 20 44 6f 63 75 6d 65 6e 74 73 5c 97 5c 92 e8 95 5c 2e 64 6f 63 0a
C : \ M y D o c u m e n t s \ \ è \ . d o c \n

また。\n のように \ には次の1バイトを特別扱いするというきまりをもつプログラム言語やスクリプト言語もありますから、そこに Shift_JIS を使うのはトラブルの元です。

EUC-JP や UTF-8 なら、このようなことはありません。

EUC-JP

8ビットを使い、日本の文字は2バイトで表します。半角カナを1バイト表現するのをあきらめて、第1バイトを半角カナの部分にも配置しました。第1バイトの種類が多い分第2バイトが少なくて済みますから、US-ASCIIの範囲を避けて配置しました。

その結果、第1バイトだけをみても第2バイトだけを見てもUS-ASCIIと同じになることはなく判断に迷うことがありません。日本の文字を考慮せずに作られたソフトウェアもそのまま動くことが多く、プログラマに優しい文字コードとして人気がありました。主にUNIXの標準文字コードとして使われていました。

41 42 43 a4 a2 a4 a4 a4 a6 a4 a8 64 65 20 31 32 a4 ab a4 ad a4 af 0a
A B C d e 1 2 \n

日本語と英語は同時に扱えるのですが、ドイツ語、フランス語など ISO-8859-1 を必要とする言語や韓国語、中国語などと一緒に使うことができません。(もちろんShift_JISもこの事情は同じです。ISO-2022-JP については 1bで始まる特別な文字の並びの決め方で対応できます)

UNIX/Linuxも次のユニコードへの移行が進んでいます。

Unicode/ISO 10646

あらゆる国の文字が混ぜて表示できるように(対訳などでは必要です)ひとつの統一された文字コードを作ろうという動きがあり、アメリカを中心とする企業からなるユニコードコンソーシアムにより Unicode ができました。ISOでも独自の研究がなされていましたが Unicode を取り込むことにして一部がISO/IEC 10646 として標準化されています。多少違うところもあるようですが一般的にはおおざっぱに Unicode と呼ばれています。

Windowsの内部コードを始めMac、LinuxなどのOSでもUnicodeを使うようになってきました。

当初は2バイトで全部入れられると思いこんでいたものが無理だとわかったり、いろいろ紆余曲折があって、同じ Unicode でもいろいろな表現ができてしまいました。

UCS-2

ISO/IEC 10646 が Unicode の基本多言語面 (BMP; Basic Multilingual Plane) をそのまま規格とした2バイト(16ビット)固定長の文字コード。UCS-4のサブセット(一部分)となっています。

Unicodeは当初2バイト(16ビット)で全部の文字を入れられると思いこんでいましたが、入りきらずに、5ビット分を拡張して21ビットの文字コードになりました。この拡張をする前の16ビットで表現できる部分が基本多言語面 (BMP) です。

UCS-2ではBMPに入っていない文字は使うことはできず、UCS-4をつかうことになります。サロケートペアという言葉が出てきたら UCS-2ではなく、Unicode の規格である UTF-16 のことです。

41 00 42 00 43 00 42 30 44 30 46 30 48 30 64 00 65 00 20 00 31 00 32 00 4b 30 4d 30 4f 30 0a 00
A B C d e 1 2 \n

すべての文字が2バイトで表されるので、US-ASCIIの1バイトの文字も00を加えて2バイトであす。

本当は 「A」は「0041」なのですが、逆順になっています。UCS-2 にはバイト順を逆にするのは聞いたことがありません。UCS-4でも「000041」です。後に説明するUTF-16の影響かも知れません。

UCS-4

ISO/IEC 10646 の4バイト(31ビット(最上位は0に固定))固定長の文字コード。4バイトは、順に群 (group)、面 (plane)、区 (row)、点 (cell) と呼ばれます。このうち第0群第0面の区点で表現される文字は UCS-2 と同じです。つまり Unicode の BMP とも同じです。UCS-4 でもおなじく基本多言語面 (BMP; Basic Multilingual Plane)とよばれています。現在の所、第0群第1面~第16面までの範囲だけに文字が定義されています。Unicode と歩調を合わせています。

00 00 00 41 00 00 00 42 00 00 00 43 00 00 30 42 00 00 30 44 00 00 30 46 00 00 30 48 00 00 00 64 00 00 00 65 00 00 00 20 00 00 00 31 00 00 00 32 00 00 30 4b 00 00 30 4d 00 00 30 4f 00 00 00 0a
A B C d e 1 2 \n

ということは、今はまだ4バイト目は常に0ということですね。

UTF-16

Unicodeは当初2バイト(16ビット)で全部の文字を入れられると思いこんでいましたが、入りきらずに、5ビット分を拡張して21ビットの文字コードになりました。この拡張した分については4バイトで表現をします。16ビットで表現できる部分はUCS-2と同じです。

16ビットでは約6万個の文字を表現できますが、その中の2048個を単純には使わないこととします。この2048の前半1024個の一つと後半1024個の一つを組み合わせて32ビットで文字を表すと1024×1024で約100万の文字を表すことができます。これをサロゲートペアといいます。

日本の文字の大半は16ビットのBMP内に収まっています。

UTF-16にはバイトの並べ方に2つの方針があります。その2つはビッグエンディアン(BE)、リトルエンディアン(LE)の2つです。

UTF-16 BE

00 41 00 42 00 43 30 42 30 44 30 46 30 48 00 64 00 65 00 20 00 31 00 32 30 4b 30 4d 30 4f 00 0a
A B C d e 1 2 \n

UTF-16 LE

41 00 42 00 43 00 42 30 44 30 46 30 48 30 64 00 65 00 20 00 31 00 32 00 4b 30 4d 30 4f 30 0a 00
A B C d e 1 2 \n

「A」のコードは 0041 ですが(これをU+0041と書きます)、00が上位バイト、41が下位バイトです。上位から読み込ませる方針がビッグエンディアン、下位から読み込ませる方針がリトルエンディアンです。(エンドは終わりでなく端の意味)

上位バイト
(big)
下位バイト
(little)
00 41

BE, LEが紛らわしい時は、BOM(Byte Order Mark)を入れます。最初に U+feff を書きます。これは幅ゼロの行末分離禁止の空白文字で、U+fffe という文字が「ない」のでこれでBE,LEの区別が付くというわけです。

このBOMはあってもなくてもよく、省略されてLEと明確に指示しない時はBEと判断することになっています。また、ネットワークに流れるデータはBEとすることになっています。

BEの方に傾倒した規定にかかわらずLEを見かけることが多いのはWindowsをはじめとする個人用OSの多くがLEの方式を使うインテルのCPUをターゲットに設計されていることによるようです。

geditはBE,LEの指定のないUTF-16でファィルの保存をするとBOMを付けてLEで書き出しますが、末尾にも付いています。UCS-2もLEですがこれらの理由は不明です。

UTF-16 (BOM使用)

ff fe 41 00 42 00 43 00 42 30 44 30 46 30 48 30 64 00 65 00 20 00 31 00 32 00 4b 30 4d 30 4f 30 ff fe 0a 00
A B C d e 1 2 \n

UTF-8

Unicode の中でも最も触れることが多いのがUTF-8です。US-ASCIIの文字はそのまま1バイトで表現できます。その代わり日本の文字は3バイトになってしまいます。

UTF-8はUCS-4の全てのコードを1バイト~6バイトの可変長に換算して作られます。(ただしUTF-16の範囲は4バイトで表現可能で、これ以上はのびない様子)

41 42 43 e3 81 82 e3 81 84 e3 81 86 e3 81 88 64 65 20 31 32 e3 81 8b e3 81 8d e3 81 8f 0a
A B C d e 1 2 \n

換算表です。

16進4バイト範囲 その0でない部分の二進表現 UTF-8 の二進表現
(1) 00 00 00 7fまで 0xxx xxxx 0xxx xxxx
(2) 00 00 07 ffまで 0000 0yyy xxxx xxxx 110y yyxx 10xx xxxx
(3) 00 00 ff ffまで yyyy yyyy xxxx xxxx 1110 yyyy 10yy yyxx 10xx xxxx
(4) 00 1f ff ffまで 000z zzzz yyyy yyyy xxxx xxxx 1111 0zzz 10zz yyyy 10yy yyxx 10xx xxxx

たとえば、

「あ」は 30 42
二進では 0011 0000 0100 0010
これは(3)の範囲なので、 1110 0011 1000 0001 1000 0010
これを16進で読むと e3 81 82

略語表

UCS Universal Multiple-Octet Coded Character Set
UTF(ISO/IEC) UCS Transformation Format
UTF(Unicode) Unicode Transformation Format
BMP Basic Multilingual Plane
BOM Byte Order Mark
聖愛中学高等学校
http://www.seiai.ed.jp/
Jun. 2009