日本語文書文字集合の指定方法

 インターネット上で日本語を扱う際には、現在、3種類の文字コードが使われています。いずれも1文字を2バイトで表しますが、1バイトを 7 bit で表すものと、8 bit で表すものとがあります。
 実はこれ、『文字符号化方式』であって、元になる『符号化文字集合』にはいずれも別途に JIS で決めた文字の集まり(JIS X 0208) + 独自拡張を使っていたりするんで、この際区別しときましょうか。

符号化文字集合

「コンピュータではこの字を使う」と決めた、表のような字引のような存在。それぞれの字を実際にどのように表現するかは、また別の問題。

JIS X 0201
まだコンピュータに漢字が使えなかった頃から存在する、アルファベットとカタカナだけが収録された規格。いわゆる『半角カナ文字』を収めたもの。
JIS X 0208
今日なお漢字を書くのに使われている規格。何度か改訂されているので、版によって別の字が収録されてたりする。
当初は収録された全ての字を実装することが難しかったので、これを第1水準と第2水準に分けて使うというやり方が行われた。
JIS X 0211
調べるまで全然知らなかったが、制御文字を収録した規格。JIS X 0201にも JIS X 0208 にも、改行文字とかの制御文字は収録されていないんだと。
JIS X 0212
せっかく作ったのに、ほとんど使われていないらしい。
JIS X 0208 第3水準・第4水準
JIS X 0208 で足りない文字を補うために検討されている規格。さて、どうなることやら。
Unicode
世界中の文字ことごとくを16ビットコード一つに収めてしまおうという無茶な企画から生まれた規格。結局は拡張して使うことになっているらしい。

文字符号化方式

 で、決められた文字にコードを割り振って、バイトで表される空間に収める工夫が必要なわけです。

ISO-2022-JP
通信に使用するため、ASCIIコードと同等の7ビットコードとして設計されています。(メールを中継するSMTPは、もともとASCIIコードを通すことだけを念頭に置いていたため、7ビット仕様になっていました。)「JISコード」と呼ばれている文字集合は、もっぱらこれを指しています。
ただし、ISO-2022-JPはJISそのものではなく、ASCIIとJIS X 0201のローマ字とJIS X 0208の1978年版とJIS X 0208の1983年版を切り替えて使う方法を指しています。
だからこれが character set だというのは、ちょっと違う気もしますが。
Shift_JIS
別名「MS漢字」とも呼ばれており、日本のPCで広く使われている8ビットコードです。JIS X 0201, JIS X 0208, それに各社の独自拡張文字が収録されています。無理にでも JIS X 0201 が必要とされたのは、移行期の象徴でしょうか。
この Shift_JIS は、1バイトが8ビットです。さらに、8ビット+8ビットの構成をフルに生かして、突っ込めるだけ突っ込んだようなコードになっています。
  1. 第1バイトに JIS X 0201 を突っ込む。(つまり『半角カナ文字』は1バイト)
  2. 空いたところを第1バイトとし、それに第2バイトをくっつけたものを、一つの文字と考える。
  3. 第1バイトの残り + 第2バイトの領域 として確保された空間に、 JIS X 0208 を突っ込む。
  4. それでもまだ空いている空間に、ベンダが勝手に定義した字を突っ込む。
  5. 残った未定義領域の一部は、外字を入れる場所として提供。
と、「空いたところに押し込む」ために、元の JIS X 0208 をぶった切ったり歪めたりしているものですから、「JISコードの表上の位置をずらしてつくったコード」という意味で、シフトJISの名があります。
だからこれが character set だというのは、ちょっと違う気もしますが。
なお、SMTPの機能拡張版であるESMTPは問題なく8ビットコードを通しますが、SMTPは7ビットコードしか通さないので、8ビットコードを7ビットコードに書き直さないかぎりメールの文字情報が欠落することになります。
EUC-JP
Shift_JIS に似た8ビットコードですが、後発だけに、ずっとマシな作りになっているようです。ASCII, JIS X 0201カタカナ, JIS X 0208, JIS 0212 と4通りの規格が使えるようになっています。
その名は Encoded UNIX Code の略で、正に UNIX のためのコードです。HTTP サーバの多くは UNIX で動いているので、CGI プログラム等で日本語を処理する際にこれが使われます。
だからこれが character set だというのは、ちょっと違う気も… えー加減にせんかい(殴)

以下は、IANAにおける登録事項です。

Name: ISO-2022-JP  (preferred MIME name)               [RFC1468,Murai]
MIBenum: 39
Source: RFC-1468 (see also RFC-2237)
Alias: csISO2022JP

Name: Shift_JIS  (preferred MIME name)
MIBenum: 17
Source: A Microsoft code that extends csHalfWidthKatakana to include 
        kanji by adding a second byte when the value of the first 
        byte is in the ranges 81-9F or E0-EF.
Alias: MS_Kanji 
Alias: csShiftJIS

Name: Extended_UNIX_Code_Packed_Format_for_Japanese
MIBenum: 18
Source: Standardized by OSF, UNIX International, and UNIX Systems
        Laboratories Pacific.  Uses ISO 2022 rules to select
               code set 0: JIS Roman (a single 7-bit byte set)
               code set 1: JIS X0208-1990 (a double 8-bit byte set)
                           restricted to A0-FF in both bytes
               code set 2: Half Width Katakana (a single 7-bit byte set)
                           requiring SS2 as the character prefix
               code set 3: JIS X0212-1990 (a double 7-bit byte set)
                           restricted to A0-FF in both bytes
                           requiring SS3 as the character prefix
Alias: csEUCPkdFmtJapanese
Alias: EUC-JP  (preferred MIME name)

 このように、IANAに登録されているので、3種類とも事実上の国際規格ということになるでしょう。SMTPとは異なり、HTTPはオクテット、すなわち8ビットを通すように設計されていますので、Web上では8ビットの文字集合も使うことができるのです。(半角カナを使用するのは危険ですが。)主要なWebブラウザは、この3種類の日本語文字集合に対応しています。
 character set というよりは encoding じゃないかという意見があって当然ですけど、Media Type としては encoding とは言わず、character set と呼んでいます。ガタガタ言わずに覚えましょう。って、自分で言ってるし(自爆)

 ただし、日本語文字集合の判別にWebブラウザが失敗すると、文字化けを起こします。
 これについて、これまでの歴史的な経過をまとめますと

  1. HTML2.0で定義されたThe HTML Coded Character SetはISO-8859-1が基になっていた。
    同時にISO-10646を扱うようにすることが推薦されており、ISO-2022-JPはISO-10646のサブセットとして、HTMLにおいて使用可能であることが明言されている。

  2. RFC2045 - RFC2049でMultipurpose Internet Mail Extensions (MIME) が規定された。
    RFC2045では、RFC1049にいうContent-Type header fieldについての規定があり、その語法は次のようになる。
         content := "Content-Type" ":" type "/" subtype
                    *(";" parameter)
                    ; Matching of media type and subtype
                    ; is ALWAYS case-insensitive.
    
         parameter := attribute "=" value
    	
    その使用例として
    Content-type: text/plain; charset="us-ascii"
    が挙げられている。さらに、新規なsubtypeの定義として

    1. Private values (starting with "X-") may be defined bilaterally between two cooperating agents without outside registration or standardization. Such values cannot be registered or standardized.
    2. New standard values should be registered with IANA as described in RFC 2048.

    の2つがある。かくて新規subtypeはIANAに登録されたもののほか、"X-"開始記号を持つ独自拡張が許された。

  3. その後、RFC2070において、HTMLの国際化が規定された。これは HTML i18n と呼ばれる。
    LANG属性やCHARSET属性など数々の新機能を加えて、HTML DTDを書き直している。このHTML DTDは"-//IETF//DTD HTML i18n//EN"である。
    the external character encodingに関する指示はHTML自体には含まれず、HTTP protocolやe-mailで使われるMIMEなど外部の機構によるとされている。従ってHTTP応答ヘッダの"Content-Type"フィールド中の"charset"に指示するということで、HTTP応答ヘッダが

    Content-Type: text/html;charset=ISO-2022-JP

    の一行を含んでいればよいという。これをincludeする方法の一つとして
    	<META HTTP-EQUIV="Content-Type"
    	 CONTENT="text/html;charset=ISO-2022-JP">
    	 
    を文書のHEADのできるだけ初めのほうに置くことができる、とある。

  4. Netscapeはこれを受けて、MozillaがISO-2022-JP,Shift_JIS,EUC-JPを表示できるように設計した。
    当時はShift_JIS,EUC-JPはまだIANAに登録されていなかったので、独自拡張としてcharset=x-sjisなどとして認識できるようにした。
    	 <META HTTP-EQUIV="content-type" CONTENT="text/html;charset=x-sjis">
    	 <META HTTP-EQUIV="content-type" CONTENT="text/html;charset=x-euc-jp"> 
    	 
    の記述は、ここに始まる。従って、これはNetscape独自のHTMLである。

  5. Microsoft Internet Explorerではcharset指定がないとローカルではISO-2022-JPを認識しない。また、charset=x-sjisの指定は認識されない。つまりI.E.ではShift_JISが優先されるようだが、特にI.E.2が開発された頃にはShift_JISはIANAに登録されていなかったせいか、Shift_JISでも文字化けを起こした。

  6. 今日では、Shift_JIS,EUC-JPがIANAに登録されたので、
    <META HTTP-EQUIV="Content-Type"
    	 CONTENT="text/html;charset=Shift_JIS">
    
    	<META HTTP-EQUIV="Content-Type"
    	 CONTENT="text/html;charset=EUC-JP">
    	 
    は、いずれも正式なHTMLである。Mozilla3,IE3はこの記述がなくても正しく表示できるようである。

  7. Mozilla4になってからは、この記述を欠いていると自動選択がおかしくなり、文字化けすることがある。特に、別のページへ飛んだ際、行先のページの文字集合の種類が異なっていても、文字集合指定がない限り元のページの文字集合を引き継ごうとするため、文字化けを起こす例が少なくない。

となります。 以上の点を考慮すると、お勧めできる方法としては

とすることが考えられます。 ただし、プロバイダ指定のCGIプログラムを用いる場合においては、実装に左右され、サーバがエラーを起こす(このサイトを置いているBekkoameとか(怒)!)などということがありますので、必ず動作を確認してから使用してください。


追記

MS-I.E.が文字化けを起こしやすいことは上述したとおりですが、これに対する処方が報告されています。それは

改行コードをLFにする

というものです。これは「やってみたら、そうなった」という話なので、再現性のあるものかどうかはわかりません。HTMLの規格上は、改行コードはCR,LF,CRLFの3種類を使用できることになっており、CRLFとLFとで異なった動作をする理由はないはずです。つまり、これについての原因は不明です。MS-I.E.の文字化けに悩む人はお試しください。もし、これで見事に文字化けが直ったなら、ぜひこちらへお知らせください。


追記 98.9.12

この件について、W3Cの村田真さんからメイルを頂きました。いろいろ納得できないこともあったので、いくつか質問などさせて頂いたところ、丁寧なお答えをいただきました。要約すると

この情報をホームぺージ・クリエイターズ・フォーラムに流したところ、いくつか疑問な点も見つかったので、補足します。

Q1. Web掲示板はCGIで自動作成するためにEUC-JPを用いるが、その時の指定方法は?
A1. CGIプログラム中でMIMEヘッダを書き出しているはずだから、その部分をtext/htmlからtext/html;charset=EUC-JPに変えればよいのではないか。つまり

print "Content-type: text/html; charset=iso-2022-jp\n\n";

とする。
Q2. 同一階層内で異なる文字集合を使いたい場合はどうするのか?
A2. 異なる文字集合を用いているファイルの拡張子を .html2, .html3 などとして区別する。そしてその上で、Apacheサーバなら.htaccessに
AddType "text/html; charset=Shift_JIS" html2
などと指定しておく。 参考1 参考2 なお、CERN-httpdでは
AddType .html2 text/html;charset=iso8859-2 8bit
というように順序が逆で、パラメタ文字列に空白を挟んではならない。

いやあ、なかなか難しいですね。しかしこれをやらないと、日本語で書いたHTML文書は読めなくなってしまうかもしれません。
というわけで、賛同される方は以下の提案を宣伝なさってください。見返りはまったくありませんが。

  1. .htaccessを書ける人は、
    AddType "text/html; charset=iso-2022-jp" html
    と書いて置きましょう。
  2. プロバイダなどのroot(管理者)がSSI禁止などして自分で.htaccessを書けない場合は、rootに.htaccessを書いてもらうようお願いしましょう。
  3. 動作は保証されないものの、METAを書いておけば、対応するクライアントに対しては有効です。
Copyleft 1998 魔術幻燈
poetlabo@cap.bekkoame.or.jp