Character Sets

この頁では、「文字セット」と「文字コード」の違い、HTTPで用いられる日本語文字セット、「文字化け」や「半角カナ」について解説します。

文字セットとは

RFC 2616のsection 3.4は、HTTPで用いられる文字セットについて記述されています。

HTTP では、"文字セット" という用語を MIME で表現される場合と同じ定義で使用する。

このドキュメント中では "文字セット" という用語を、一つ以上のテーブルを使ってオクテットシーケンスを文字シーケンスに変換するための方法を述べるために使う。 与えられた文字セットですべての文字が利用できるわけではなかったり、文字セットがある特定の文字を表すために一つ以上のオクテットシーケンスを供給する場合でも、別の指示による無条件な変換が必要でないは事に注意せよ。 この定義は、US-ASCII のような簡単な単一テーブルマッピングから、ISO-2022 の技術を使うような複雑なテーブルをスイッチする 方法まで、さまざまな種類の文字エンコーディングを認めようとするものである。 しかし、MIME 文字セット名に関係付けられる定義は、1 オクテットから文字へと実行される写像{mapping} を完全に規定しなければならない。 特に、正確な写像を決定するために外部プロフィール情報を使用する事は許されない。

注: ここで使われる "文字セット" という用語は、より一般的には "文字エンコーディング" という語で述べられる。 しかし、HTTP と MIME とで同じ登録を共有しているので、用語もまた共有される事は重要な事である。

文字セットに関するお薦め書籍

ところで、この「文字セット」と似た言葉に「文字コード」という語があります。 また、上の文章には「文字エンコーディング」という単語が現れました。 これらは、以下のように整理することができます。

文字セット {character set}
日本語訳すれば文字集合。 すなわち、ある文字の集合を定義したもの。 文字セットという概念は、コンピュータ上の規格に限定されるものではなく、例えば常用漢字人名用漢字なども文字セットであると言える。
文字コード {character code}
日本語訳すれば文字符号。 すなわち、文字セット中の文字一つ一つに割り当てられた一意なデータコード。 たとえば、ASCIIという文字セットには“A”という文字が含まれており、この文字には0x41という文字コードが割り当てられている。
文字エンコーディング {character encoding}
日本語訳すれば文字符号化処理(方式)。 すなわち、文字セット中にある文字(“A”や“あ”)を、文字コード(“0x41”や“0xA4 0xA2”)に対応させる処理。 日本語を扱うものにはISO-2022-JP, Shift_JIS, EUC-JP, UTF-8などがある。

RFC 2616においては、IANAにて登録されている(※)、及びこれから登録されるであろう文字エンコーディングのみを議論するので、「文字セット」と「文字エンコーディング」の二語を同一視しています。 以下、この文書でも「文字セット」で統一します。

(※) 現在、IANAに登録されている文字セット(文字エンコーディング)は、http://www.iana.org/assignments/character-setsで確認することができます。

本来の意味における「文字セット」としては、以下のようなものがあります。

ASCII

ASCII文字セットの定義は、ISO 646-1991 という規格書に記載されています。 ASCII文字セットは7ビットで表現可能な量である128文字で構成されますが、このうち表示可能な文字は94文字であり、残りの34文字は空白文字と、ヌル文字・タブ・改行といった制御文字と呼ばれるものです。

JIS X 0201

JIS(日本工業規格)とは、日本の工業の標準化を進めるための国家規格の事です。 コンピュータで日本語扱えるようにするために、1976年にJIS C 6220と呼ばれる規格が作られました。 1987年 には、JIS は多くの規格について“C”を“X”と改称する決定が行われ、JIS C 6220JIS X 0201と改称されました。

JIS X 0201は、ローマ字セットとカナ字セットからなります。 このうち、ローマ字セットはASCIIを基にしていますが、ISO 646 にてその割り当ての変更が認められている文字のうち、0x5Cを“\”から“¥”へ、0x7Cを“破断線”から“|”へ、また0x7Eを“〜”から“ ̄”に置き換えたものです。

(※) 便宜上、各記号は全角文字です。 また“破断線”は、ASCIIコードの種類によっては破断線ではなく縦線を用いているものがあります。

JIS X 0201 ローマ字セットの文字コード表
0 1 2 3 4 5 6 7 8 9 A B C D E F
0 NUL SOH STX ETX EOT ENQ ACK BEL BS HT LF VT FF CR SO SI
1 DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US
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 { | } ~ DEL

また、カナ字セットはいわゆる半角カナであり、日本語文を書くのに最低限必要な句読点と記号を含む63文字からなります。 半角カナは、ローマ字モードからエスケープシーケンスを用いてカナ字モードへ変換する事で使用できるようになる「JIS7」と呼ばれるものと、第8ビット(具体的には0xA10xDF)を用いるJIS8と呼ばれるものがありますが、どちらの場合も1バイトで文字を表現します

JIS X 0208

JIS X 0201 では英数字とカタカナしか使えません。 そこで、日本語表記にもっと適した電子文字セット規格が作られました。 1978 年に JIS C 6226-1978 という文字セットが制定され、1983 年に JIS C 6226-1983 と改訂されました。 また 1987年 には、前述の通り JIS C 6226-1983JIS X 0208-1983 と改称されました。 その後も改訂が行われ、改訂された年に合わせてそれぞれ JIS X 0208-1990, JIS X 0208-1997 と呼ばれています。

JIS X 0208 では 2 バイトを使って文字を表現し、文字領域として 94 区× 94 点のマトリクスを持っています。 この 94 × 94 マトリクス内の位置を表すコードを区点コードと呼び、94 区内における文字配列は以下のようになっています。

(※) どうして「94」なのかと言えば、ASCII において表示可能な文字が 94 文字であるから (0x21 〜 0x7E) に他なりません。

JIS X 0208 における文字配列
文字種
1-2各種記号
3英数字
4ひらがな
5カタカナ
6ギリシャ文字
7キリル文字
8罫線素片
9-15未定義 (自由領域)
16-47JIS 第一水準漢字
48-84JIS 第二水準漢字
85-94未定義 (自由領域)

JIS X 0208 は、コンピュータ上で日本語の文書を扱う時の日本の標準規格なので、すなわち 「日本語対応」のコンピュータであれば JIS X 0208 で規定されている全ての文字が扱えると考えていいでしょう。

JIS X 0212

JIS X 0212 は、1990 年 10 月 1 日に JISC (日本工業標準調査会) によって制定され、6067 文字の補助漢字文字セットが収められています。 これらの漢字は JIS X 0208-1990 の漢字に対して追加されたもので、先の文字セットと同じく 94 区× 94 点の文字領域を持っています。

JIS X 0212 における文字配列
文字種
1未定義 (保留領域)
2各種記号
3-5未定義 (保留領域)
6ギリシャアルファベット
7キリルアルファベット
8未定義 (保留領域)
9-11キリルアルファベット
12-15未定義 (保留領域)
16-77補助漢字
78-84未定義 (保留領域)
85-94未定義 (自由領域)

(※) 但し、Shift_JIS では余分な領域が残っていないため、これらの補助文字を符号化する事ができません。 EUC-JP ではこの問題は解消されています

Unicode

世界中には色々な文字がありますが、これらを一つの文字コード体系で扱える事ができれば、ある国のエディタで書かれたファイルを、特別な処理を行う事なく、別の国のテキストリーダで読む事ができます。 そこで、世界の工業標準を定める ISO は、世界中のローカルな文字を一つにまとめて同時に利用できる、新たな文字コード ISO 10646 の検討を始めました。 一方、ほぼ同じ頃、アメリカでは、Apple 社、IBM 社、Microsoft 社等の企業が中心となって、16 ビット (= 2 オクテット) で世界中の文字を表現する事を目指した文字コードである、Unicode を開発する動きが出てきました。 これらは当初、別々に開発が進められていましたが、目的が同じものを二つ作るのはよくないとして、Unicode 側の仕様を軸に統合が行われ、1993 年に ISO 10646-1 として成立しました。 その後、ISO 10646-1 は、JIS X 0221 として JIS 規格にもなりました。

ISO 10646 は UCS と名付けられています。 UCS は、4 バイトで文字コードを表す UCS-4 と、その内の一部の文字である基本多言語面 (BMP) を 2 バイトで表す UCS-2 とがあります。 Unicode では、文字コードの事を特にコードポイントと呼び、一般に U+HHHH (“H”は16進数) と記述されます。

(※) Javaの世界では\uHHHHと表現されることもあります。

HTTPで用いられる日本語文字セット

HTTPで文字セットを表現する場合について、引き続きRFC 2616のsection 3.4をご覧下さい。

HTTP 文字セットは大文字・小文字を区別しないトークンによって識別される。 トークンの完全なセットは、IANA の文字セット登録機構 [19] によって定義される。

 charset = token

HTTP では、文字セットの値として独自のトークンを使用する事を認めているが、IANA の文字セット登録機構 [19] によって定義済みであるトークンは、すべてその登録機構で定義された文字セットを表さなければならない。 アプリケーションは、使用する文字セットを IANA の登録機構によって定義されたものに制限すべきである

HTTP アプリケーションの開発者は、IETF の文字セット要求を認識すべきである [38] [41]

HTTPでは、リソース中の文字セットについての制約はないので、日本語を表現するための「ひらがな」「カタカナ」「漢字(※)」などを含む文字セットを使用することができます。 日本語を表現するための文字セットとしては、ISO-2022-JP, Shift_JIS, EUC-JP, UTF-8があります。

(※) 漢字を使う言語には中国語もありますが、大きく分けて、中国本土やシンガポールなどで使用される簡体字と、香港や台湾などで使用される繁体字があります。 簡体字を含む文字セットにはGB2312GBK, また繁体字を含む文字セットにはBig5などがあります。

ISO-2022-JP

しばしば、"JIS コード" とも呼ばれます。 既に JUNET 等でメールやネットニュースのために利用されていた文字セットですが、1993 年に発行された RFC 1468 で勧告されました。

テキストは ASCII にて始まり、エスケープシーケンスを通じて日本語文字に切り替える。 例えば、エスケープシーケンス ESC $ B (3 バイト, 16 進値: 1B 24 42) はそれ以降が日本語文字である事を示し、2 バイト毎にエンコードされる。 ASCII へと戻すためには、エスケープシーケンス ESC ( B が使われる。

以下の表は、ISO-2022-JP メッセージにて使用されるエスケープシーケンスと文字セットを与えるものである。 ISOREG 番号は ISO 登録機構での登録番号である。

 Esc Seq    Character Set                  ISOREG

 ESC ( B    ASCII                             6
 ESC ( J    JIS X 0201-1976 ("Roman" set)    14
 ESC $ @    JIS X 0208-1978                  42
 ESC $ B    JIS X 0208-1983                  87
 message             = headers 1*( CRLF *single-byte-char *segment
                       single-byte-seq *single-byte-char )
                                         ; [MIME1] "body-part" も参照
                                         ; 注意: ASCII で終わらなければならない
 headers             = <[RFC822] "fields" と [MIME1] "body-part" を参照>
 segment             = single-byte-segment / double-byte-segment
 single-byte-segment = single-byte-seq 1*single-byte-char
 double-byte-segment = double-byte-seq 1*( one-of-94 one-of-94 )
 single-byte-seq     = ESC "(" ( "B" / "J" )
 double-byte-seq     = ESC "$" ( "@" / "B" )
 CRLF                = CR LF
                                                  ; ( Octal, Decimal.)
 ESC                 = <ISO 2022 ESC, escape>     ; (    33,      27.)
 SI                  = <ISO 2022 SI, shift-in>    ; (    17,      15.)
 SO                  = <ISO 2022 SO, shift-out>   ; (    16,      14.)
 CR                  = <ASCII CR, carriage return>; (    15,      13.)
 LF                  = <ASCII LF, linefeed>       ; (    12,      10.)
 one-of-94           = <任意の 94 の値の内の一>   ; (41-176, 33.-126.)
 7BIT                = <任意の 7-bit 値>          ; ( 0-177,  0.-127.)
 single-byte-char    = <任意の 7BIT, 単一の CR 及び単一の LF は含むが、CRLF は含まない
                        また ESC, SI, SO は含まない>

JIS X 0201 の Kana セットは ISO-2022-JP メッセージ中では使用されない。

以前は、誤って JUNET メッセージ中でエスケープシーケンス ESC ( H を使用していたシステムもあった。 このエスケープシーケンスはスウェーデン語文字セットのために公式に登録されており、そのため ISO-2022-JP メッセージ中には使用すべきではない。

このように ISO-2022-JP は、JIS X 0201 のローマ字セット、JIS X 0208-1978JIS X 0208-1983 からなる文字セットです。

RFC 1468 内に記述されている BNF から明らかなように、ISO-2022-JP を構成する文字コードは全て 7 ビットとなっています。

また、JIS X 0201カナ字セットは、ISO-2022-JPでは使用されません。 あわせて、『いわゆる「半角カナ」について』もお読み下さい。

Shift_JIS

Microsoft 社が開発した文字セットで、"MS 漢字コード" や "SJIS" とも呼ばれます。 日本語 MS-DOS, Windows, Macintosh 等のパーソナルコンピュータでは内部コードとして標準的に用いられています。 Shift-JIS という名称は、2 バイト文字のコード位置が JIS8 における "半角カナ" (具体的には 0xA10xDF) とぶつからないようにシフトした事に由来します。 従って Shift-JIS では、エスケープシーケンスを使用する事なく "半角カナ" も使用する事ができます。

2 バイト文字における第 1 バイトは 0x810x9F 及び 0xE0〜0xFC となっており、JIS X 0201 ローマ字やカナ字とは重複しないように配置されています。 但し、2 バイト文字における第 2 バイトは 0x400x7E 及び 0x800xFC であり、特にプログラムを作成する場合には 0x400x7E の範囲の文字コード (特に "\" 0x5C 等) が問題を引き起こす可能性があるので、注意が必要です。

EUC-JP

EUC とは Extended Unix Code の略で、UNIX の内部処理用漢字コードです。 EUC は日本語エンコーディング専用ではなく、中国語用の EUC-ZN や、韓国語用の EUC-KR 等も存在します。 EUC-JPISO-2022-JP を第 1 バイト・第 2 バイト共に 0x80 だけシフトさせたもので、このため "最上位ビットを立てた JIS" とか "UJIS" 等と呼ばれる事もあります。

EUC-JP における JIS X 0208 は第 1 バイト・第 2 バイト共に 0xA10xFE に配置されており、それぞれの文字コードが 1 バイト文字と重なる事が無いので、プログラムを作る観点から言えば 3 つの中で一番扱いやすい文字コードと言えるでしょう。

更に、ISO-2022-JP では使用できない "半角カナ" は第 1 バイトを 0x8E とする 2 バイト文字に、また JIS X 0212 は第 1 バイトを 0x8F とする 3 バイト文字としてそれぞれ利用する事ができます。

(※) ちなみに、当サイトの文字セットは EUC-JP で統一されています。

UTF-8

UCS は、2 バイトないしは 4 バイトでサイズが固定されていますが、その中でも英語圏で頻繁に使用される文字である ASCII は 1 バイトで情報が足りるため、結果的に無駄な 0 パディングを行っている事になります。 また、E-Mail では、メール転送プロトコルである SMTP の制約によって、7 ビット文字しか使用できないので、このままでは UCS を使用する事ができません。 そこで、UCS に適当なエンコーディングを施そうと考えられました。 これを総称して UTF と言います。

UTF にはいくつか種類がありますが、最も利用されているのは UTF-8, a transformation format of ISO 10646 にて規定されている UTF-8 です。 但し、UTF-8 を使用すると、ほとんどの日本語の文字 1 文字が 3 バイトに変換されてしまうので、サイズの点から見ると、他の文字セットよりも不利であると言えます。

いわゆる「文字化け」について

複数の文字セットに同一の文字が含まれていたとしても、その文字を表すための文字コードは異なる可能性があります。 これに関する注意点について、RFC 2616のsection 3.4.1をご覧下さい。

いくつかの HTTP/1.0 ソフトウェアは、"受領者が推測すべき" という意図で、文字セットの無い Content-Type ヘッダを不正確に解釈している。 この振る舞いをやめさせたい送信者は、例え文字セットが ISO-8859-1 の時でも文字セットパラメータを含む事ができるし、受領者が混乱する事が無いであろうという事がわかっていれば、それを含むべきである

不幸な事に、いくつかの古い HTTP/1.0 クライアントでは、明示的文字コードパラメータを適切に扱えなかった。 HTTP/1.1 の受領者は、送信者によって供給される文字セットラベルを尊重しなければならない。 そして、文字コードを "推測" する機能を持つユーザエージェントは、もしその文字セットをサポートしていれば、始めにドキュメントを表示する時に、受領者が好むものよりも content-type フィールドにある文字セットを使わなければならない。 section 3.7.1 参照。

たとえば、前節で示した4つの文字セットには、すべてに『あ』という文字が含まれていますが、それを表すための文字コードは以下のように異なります。

日本語文字セット中の文字『あ』の文字コードの比較
文字セット 2進数文字コード 16進数文字コード
ISO-2022-JP 00100100 00100010 0x24 0x22
Shift_JIS 10000010 10100000 0x82 0xA0
EUC-JP 10100100 10100010 0xA4 0xA2
UTF-8 11100011 10000001 10000010 0xE3 0x81 0x82

したがって、ユーザエージェントは「Aという文字コードで記述された文書を、Bという文字コードだと判別した」場合(※)、リソースの発行者が意図した文字とはまったく異なるものを表示してしまう、いわゆる文字化けを起こす可能性があります。

(※) より正確に表現すると、『リソースの発行者がAという文字エンコーディング(文字→文字コード)を用いてエンコードしたリソースを、ユーザエージェントがBという文字デコーディング(文字コード→文字)した場合』に、文字化けが起こります。

そこで、HTTPでは、以下のようにContent-Typeヘッダフィールドを使用して、発行者が文字セットが明示することができます。(※※)

 Content-Type:text/html; charset=EUC-JP

(※※) HTML文書の場合、HTTPヘッダを操作しなくても、<meta http-equiv="Content-Type" content="text/html; charset=EUC-JP">のように、HTML文書中に直接文字セット情報を埋め込むことができます。

いわゆる「半角カナ」について

いわゆる「半角カナ」とは、「JIS X 0201のカナ字セット」のことを指します。 JIS X 0208におけるカタカナとの違いは、カタカナを表現するためにJIS X 0201では1バイトで表現しているのに対し、JIS X 0208では2バイトを使用している点にあります。

JIS X 0201 では、英数字とカタカナだけが定義されました。 英数字は文字が縦長の形状をしているので、JIS X 0201 カタカナもそれに合わせて縦長に表示されるようになりました。 一方 JIS X 0208 では、ひらがなや漢字も定義されています。 ひらがなや漢字は正方形に近い形状をしていて、また 2 バイトであるということもあって、文字の横幅が JIS X 0201 文字の倍になるようなフォントが作られました。 そのような理由で「半角カナ」と「全角カナ」、また「半角英数字」と「全角英数字」という二つのフォントが生まれたのです。 すなわち、字形の表示幅とそれをエンコードするバイト数の間に明確な相関関係があったのです。

(※) 但し、現在ではこのような相関関係はあまりありません。 例えば、EUC-JP では「半角カナ」でも2バイトを必要とします。

ところで、たまに「WWW では『半角カナ』を使用してはならない」という意見を見ることがありますが、これは正しいのでしょうか? ここでは、「WWWにおける転送プロトコルであるHTTPで使用できるかどうか?」の観点から論じます。

電子メールの場合、メール転送プロトコルであるSMTPの制約によって、7ビット文字しか使用できません。 SMTPを規定している文書である、Simple Mail Transfer Protocol のsection 2.4をご覧下さい。

コマンドや応答は、ASCII文字セットからの文字で構成される。 転送サービスが8ビットバイト(オクテット)の転送チャネルを提供する時、各7ビット文字は最上位ビットを0にクリアしたオクテットに右詰して転送される。 特に、拡張されていないSMTPサービスでは7ビットの転送のみを提供する。 特定のサーバとの適切な拡張に関する交渉{negotiate}が成功していない初期{originating}のSMTPクライアントは、オクテットの上位ビットを含む情報を持つ転送メッセージを送信してはならない。 このルールに反してそのようなメッセージが送出された場合、受信したSMTPサーバは上位ビットをクリアしてもよいし、そのメッセージを不正として拒否してもよい

このように、メールでは8ビット文字を送信すると、メールサーバに文字コードを変換されたり、メールサーバに拒否されるかもしれないので、メールにおいて日本語を扱うためには文字が7ビットのみで構成されているISO-2022-JPを使用するしかないのです。

しかしながら、ISO-2022-JPにはJIS X 0201カナ字セットは含まれていません。 したがって、電子メール上では、その転送プロトコル上「半角カナ」を使用することはできないのです。 同様に、文字セットにISO-2022-JPを用いたHTML中では「半角カナ」を使用してはいけません。

一方、HTTP においては、8ビット文字が通信可能であることが RFC 2616 の section 2.2に記述されています。

 OCTET           = <8-bit のデータシーケンス>

以上より、8ビット文字を扱う文字セットであるShift_JISEUC-JPを用いて記述されたHTML文書では「半角カナ」を使用できますし、またそれをHTTPで転送することも可能です。 したがって、通信プロトコルにHTTPを使う以上、WWWでは『半角カナ』を使用することができるのです。

(※) 「半角カナ」を用いる場合に文字セットを明示しないと、ブラウザなどによる文字セットの自動判別の誤りによって間違ってエンコードされる、いわゆる文字化けを起こす可能性があります。 また、JIS X 0208-1997では、Shift_JISの「半角カナ」 は将来廃止して、そのコード空間を漢字の拡張にあてるという方向性が示されています。 他にも見栄えなど、いくつかの理由から、WWWにおいて「半角カナ」は使用すべきではない、と考える人もいます。 よって、WWW上での「半角カナ」の使用は、上記の点も考慮に入れた上で利用するかどうかを判断した方がよいでしょう。

参照文献

Webリソース

書籍