文字コード入門
★index
文字サイズ変更
Asciiと半角カナの時代
今日、ほとんどのコンピュータの文字コードの基本部分はAsciiといい、
(American standard code for information interchange)
1963年6月17日に、最初の版がAmerican Standards Associationによって制定された。
これはUS-Asciiともいわれます。
その詳細は以下の通り。詳しくは本編の姉妹編
▼文字コード研究 をご覧ください。
Ascii コード表
\ 0 1 2 3 4 5 6 7 8 9 a b c d e f
0 NUL SH SX EX ET EQ AK BL BS HT LF HM CL CR SO SI
10 ED D1 D2 D3 D4 NK SN EB CN EM SB EC → ← ↑ ↓
20 SP " ! # $ % & ' ( ) * + , - . /
30 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
40 @ A B C D E F G H I J K L M N O
50 P Q R S T U V W X Y Z [ \ ] ^ _
60 ` a b c d e f g h i j k l m n o
70 p q r s t u v w x y z { | } ~ DEL
この表の見方を解説します。座標軸は16進法で、横軸は0x0~0xfの桁、縦軸は0x10~0x70の桁をあらわします。
なお、16進法は英数字で0123456789abcdef または 0123456789ABCDEFであらわします。ここでは頭に0xを付けて
16進数であることを表します。
0x20はスペースです。制御コードでなく、印字動作もしない特殊な文字です。
0x7fは削除記号です。編集済テキストファイルには存在しません。紙テープやパンチカードの時代の名残りです。
Asciiという文字コードは0x00~7fの範囲で設定されていますが、1バイトであらわされる残りの部分、0x80~ffを使って
各国語対応版が作られた。日本語対応したコード系を見てみよう。
JIS X 0201 初版は1969年6月1日の制定
\ 0 1 2 3 4 5 6 7 8 9 a b c d e f
0 NUL SH SX EX ET EQ AK BL BS HT LF HM CL CR SO SI
10 ED D1 D2 D3 D4 NK SN EB CN EM SB EC → ← ↑ ↓
20 ! " # $ % & ' ( ) * + , - . /
30 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
40 @ A B C D E F G H I J K L M N O
50 P Q R S T U V W X Y Z [ ¥ ] ^ _
60 ` a b c d e f g h i j k l m n o
70 p q r s t u v w x y z { | } ~ DEL
80
90
a0 。 「 」 、 ・ ヲ ァ ィ ゥ ェ ォ ャ ュ ョ ッ
b0 ー ア イ ウ エ オ カ キ ク ケ コ サ シ ス セ ソ
c0 タ チ ツ テ ト ナ ニ ヌ ネ ノ ハ ヒ フ ヘ ホ マ
d0 ミ ム メ モ ヤ ユ ヨ ラ リ ル レ ロ ワ ン ゛ ゜
e0
f0
JIS X 0201 の痛恨事、それは0x5cのコードがUS-Asciiでは"\"であるが、JIS X 0201では"¥"になっている事です。
各国の文字
コンピュータで世界の文字を扱うために作られた規格がISO 8859です。但し、漢字とハングルは別扱いです。
ISO 8859を使えばヨーロッパ諸国のローマ字系文字やギリシャ文字、ロシアのキリル文字、トルコ文字、
ヘブライ文字、アラビア文字、タイ文字があらわせます。これを世界地図にあてはめてみると、漢字圏以外の
世界のかなりの地域が埋まっていますが、空白地帯が浮かびあがってきます。それはかつて植民地支配された国々です。
インド、パキスタン、スリランカ、バングラデシュはイギリスの植民地で、複数の公用語が用いられますが、
とりあえず英語をコンピュータ化しとけばよかったのでしょう。デヴァーナーガリの符号化も試みられましたが
計画は破棄されたそうです。
ISO 8859 下記は西ヨーロッパバージョンのISO 8859-1
ISO 8859-1
Code ..0 ..1 ..2 ..3 ..4 ..5 ..6 ..7 ..8 ..9 ..a ..b ..c ..d ..e ..f
0..
1..
2.. SP ! " # $ % & ' ( ) * + , - . /
3.. 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
4.. @ A B C D E F G H I J K L M N O
5.. P Q R S T U V W X Y Z [ \ ] ^ _
6.. ` a b c d e f g h i j k l m n o
7.. p q r s t u v w x y z { | } ~
8..
9..
a.. NBSP ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ SHY ® ¯
b.. ° ± ² ³ ´ µ ¶ · ¸ ¹ º » ¼ ½ ¾ ¿
c.. À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï
d.. Ð Ñ Ò Ó Ô Õ Ö × Ø Ù Ú Û Ü Ý Þ ß
e.. à á â ã ä å æ ç è é ê ë ì í î ï
f.. ð ñ ò ó ô õ ö ÷ ø ù ú û ü ý þ ÿ
ISO 8859のその他のバージョンについては姉妹編、文字コード研究をご覧ください。
漢字コード
日本では1978年にJIS(日本工業規格)C 6226が制定された。その後規格体系の見直しで1987年に
名称をJIS X 0208に変更しました。JIS X 0208で規定された文字数は、非漢字453文字、漢字6349文字、
合計6802文字です。16区から47区が第一水準、48区から83区が第二水準ですがその後追加がありました。
区、点、それに区の上位にあたる面について解説しておきます。
それは94進法でできています。94はAsciiコード表の0x21~0x7eまでの印刷可能文字の数です。
ほとんどのプログラム言語の配列は0から始まりますが、面、区、点は1から始まります。
理論上は1区94点の次は2区1点です。(非漢字エリアは未定義が多いので「理論上は」となります)
漢字エリアは16区1点から始まります。何面か明記してない場合は最初の面、1面です。
1面94区94点の次は2面1区1点です。
第三、第四水準の漢字が追加され、面まで使わないと表せなくなったのです。
(非公式には区を94を超えて使っている方もいらっしゃいます。)
JIS X 0208は1983年、1990年、1997年に改定され、また追加の規格として
JIS X 0212、JIS X 0213 も制定されましたが、詳細は姉妹編をご覧ください。
以降、総称として JIS X 0208 とする。
符号化文字集合と文字符号化方式
こちらは入門編なのですが、すこしだけ理屈っぽい事を書きます。
上述のJIS X 0208は符号化文字集合です。
まず有識者(?)が集まって登録する文字の取捨選択をし、グループ分けし並び順を決め区点番号を
振っています。
非漢字はグループ分けをし、何らかの基準でグループの順序を決め、グループ内の順序を決めています。
漢字は水準分けされ、第一水準漢字は読み順に第二水準は部首の画数順に順序付けられています。
そのように決められて符号化文字集合を実用の文字コードにする方式が文字符号化方式です。
日本語の文字符号化方式としてよく使われているのが
(1)JIS漢字コード
(2)SHIFT-JISコード
(3)EUC-JP
(4)Unicode系のUTF-8、UTF-16等 これについてはユニコードの項で書きます。
JIS漢字コード
JIS漢字コードは実はISO/IEC 2022という国際規格規格の一部でかなり面倒な仕様ですが、
AsciiコードとJIS X 0208コードだけを使う場合について説明します。
次の2種類のエスケープシーケンスを使います。
0x1b2842:Ascii
0x1b2442:JIS X 0208
一連のファイルやメッセージの流れの最初はAsciiと解釈されます。
次に0x1b2442が出現したらその後はJIS X 0208と解釈されます。
次に0x1b2842が来たらAsciiです。
仮に漢字の後に改行を出力するときも0x1b2842のエスケープシーケンスが必要です
JIS X 0208の1区1点は0x2121に符号化され、その他のコードも94進数の原則で符号化されます。
JIS漢字コード値=0x2020+区×94+点です。
EUC-JP
EUC(Extended Unix Code)はUNIX上でよく使われる文字コードの符号化方式です。
煩わしいエスケープシーケンスは使いません。
日本語EUCのほか各国語版がありますが姉妹編をごらんください。
日本語EUCは3つのカテゴリーのコード域を用います。
(1)0x00~7fのAsciiコード域
変換操作不要
(2)半角カナ
第一バイトに0x8eのシフトインコードを付けて
第二バイトはJIS X 0201 のコード値通り設定する。
(3)漢字コード
1区1点を0xa1a1に割り振り、その他94進の法則で割り当てる。
EUC漢字コード値=0xA0A0+区×94+点です。
SHIFT-JIS
JIS X 0208は区と点を94×94で表していますが
SHIFT-JISでは94の半分の47と2倍の188の47×188で表しています。
そのため、Windows系以外の人や日本以外の人には評判が悪いようです。
区の符号化は1区と2区のように奇数の区とそれに続く偶数の区に同じコード位置を与えている。
それを半区とすると1半区が0x81に始まるコード域に47進数の法則で割り振るのですが、
途中JIS X 0201のコード表を見れば0xa0~dfは半角カナに占められているので
0x9fの次は0xe0になる。
点の符号化は点そのもののコード値のほかに区の符号化で失われた区の奇数偶数の情報も保持する。
入門編ですけど、こんな面倒な符号化が日本のデファクトスタンダードなので勘弁してください。
区が奇数の場合、点は0x40から始まるコード域に符号化するが、0x7fが欠番になっているので
以降繰り下げ処理をします。コード域は0x40~9eです。
区が偶数の場合、点は0x9fに始まるコード域に符号化する。幸い途中に欠番は無く94点は0xfcです。
換算ロジック等は姉妹編をご覧ください。
更に面倒なはなしがあります。日本のデファクトスタンダードは純正版JIS X 0201に基づくSHUFT-JIS
ではなく、制定当事有力だったIBMやNECが使っていた拡張漢字コードを取り込んだマイクロソフトの
MS-932という文字集合に基づく物なのです。後で制定された第三、第四水準の漢字を取り込む
余地はありません。混乱の元になったIBMのPC事業はレノボに身売りされ、NECのパソコン事業は
Windows95出現以降凋落しました。
ユニコードの時代と文字集合
さきに見たようにISO-8859という規格によってヨーロッパからロシア、アラブ圏からタイに
至る地域の文字が1つの枠組みの中で統一規格とされたが、コードページの切り替えを要した。
これを統一し、足りないものを足して世界の文字を単一のコード表にしようという意図の下
ユニコードが企画された。その実行のための団体がユニコードコンソーシアムです。
ISO-8859に足りないもの、第一の要素は漢字とハングル、第二の要素は諸民族の文字です。
漢字の母国は中国であるが、本国では簡字体、台湾や香港では伝統的な繁体字が用いられ
日本では独自の進化を遂げた部分もありJIS X 0208等の文字集合になった。
その他、南北朝鮮やベトナムでも漢字は部分的に使われた。それらは歴史的に異なった
背景を持つ文字であるが、ユニコード化するとき字形により統合したCJK統一漢字とされた。
また、ハングルは100個足らずの字母で書ける。また1980年代の韓国のパソコンは2000個あまりの
完成形ハングルを搭載していたが、ユニコードの規格には考えられる組み合わせ11172個が収録された。
ISO-8859に足りないもの、第二の要素は諸民族の文字その他です。
インドやスリランカなどの諸民族の文字に始まり、古代エジプトのヒエログリフやメソポタミアの
楔型文字、古代中国の甲骨文字や金文から実態がよくわからない少数民族の文字、
携帯電話の絵文字まで取り込んだ符号化文字集合UCSが作られた。
Unicodeでは文字をあらわす符号位置(コードポイント)にUnicodeスカラ値という正の整数が
割り当てられていて、"U+"に続く16進値で表される。またそれをUCS、UCS-4という。
ユニコードの符号化式
ユニコードは文字集合を策定するという行為とは独立して文字集合を符号化する
いくつかの方式があります。
UTF-8
UTF-8は1バイト~6バイトの可変長コード化方式です。
現実には5~6バイトの符号化は近い将来考えられない。
U+00~U+7fのUs-Asciiの領域が1バイトでコード化されるという利点を持つが
漢字、非漢字など大部分の日本語コードが3バイトでコード化される事が難点である。
UTF-8ではある1バイトを見れば、そのバイトがシーケンス上に占める場所がわかる。
ビットパターン X:0または1の任意の組み合わせ
0XXXXXXX 1バイトコードである。
10XXXXXX 多バイトコードの後続バイトである
110XXXXX 2バイトコードの先頭バイトである
1110XXXX 3バイトコードの先頭バイトである
11110XXX 4バイトコードの先頭バイトである
1111111X 未定義(あるいはBOMコード)
UTF-8の符号化
データ範囲 コード化長 第1バイト 第2バイト 第3バイト 第4バイト 第5バイト 第6バイト
U+0~U+7f 1バイト 0xxxxxxx
U+80~U+7ff 2バイト 110xxxxx 10xxxxxx
U+800~U+ffff 3バイト 1110xxxx 10xxxxxx 10xxxxxx
U+10000~U+1fffff 4バイト 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
U+200000~U+3ffffff 5バイト 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
U+4000000~U+7fffffff 6バイト 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
UTF-16
UTF-16ではUCS値がU+10000未満の場合、2バイトコード、U+10000以上なら4バイトコードになります。
2バイトコードの場合、UCS値=UTF-16値になります。
ただし、U+d800~U+dfffはサロゲートエリアとして保留されていて、文字コードに割り当てられることはありません。
4バイトコードに変換する場合、USC値を10ビット値2つに分解します。
簡単に書けば1024で割った商と剰余に分けます。(1024は2の10乗です)
上位2バイトは0xd800+商、下位2バイトは0xdc0+剰余になります。
0xd800と0xdc0はサロゲートエリアの開始アドレスです。
エンディアンとBOM
ところで、UTF-16には3種類あります。
(1)BOMで始まるビッグエンディアン
(2)BOMで始まるリトルエンディアン
(3)BOMで始まらないビッグエンディアン
そこでBOMとエンディアンについて説明します。
BOMはbyte order mark で、それは0xfeffという値を各エンディアンで設定した値で、
ずばり書けばビッグエンディアンなら0x0eff、リトルエンディアンなら0xfffeです。
大きい値で終わればビッグエンディアン、小さい値で終わればリトルエンディアンです。
エンディアンは計算機の構造を表す言葉です。
さきに書いたように、0xfeffというのが符号なし整数値だとしたら
それを0xfeffとメモリーに格納するやり方はIBM、モトローラMC68000系、サンマイクロシステムのSPARC、
それにJava Virtual Machine はこの流儀に従い、ビッグエンディアンです。
他方、インテルのX86系やDECのVAXなどは0xfffeとメモリーに格納し、リトルエンディアンです。
★index ▼外部リンク △TOP