今日はISO 2022とISO-2022-JPについて解説します。まずあらすじを述べます。

Actitis hypoleucos 1 (Marek Szczepanek)

 ISO 2022は国際的な規格機関ISOが制定した、文字コード表を必要に応じて切り替えるための仕組みです。すでに出てきたASCII、JIS X 0201、JIS X 0208、および、今日の後半登場するISO-2022-JPは、ISO 2022に準拠した文字コードです。一方、まだ出てきていませんが過去日本で最も使われていたShift_JISや、世界で主流になっているUnicode(UTF-16やUTF-8)は、ISO 2022に準拠していません。

 ISO-2022-JPは、ISO 2022を使ってASCII、JIS X 0201(半角カナを除く)、JIS X 0208を切り替えて使える文字コードです。これはもともと日本発の文字コードで、ISOが制定したものではありません。ISOと2022の間にハイフンが入っているのに注意して下さい。

ISO 2022

 まず、ISO 2022について述べます。ISOと2022の間が空白であることに注意して下さい。これは、スイスのジュネーブに本部を置く規格機関ISOが制定した、文字コードよりも高次の(抽象的な)枠組みです。非常に複雑な仕組みで、ぼくも全容は知りません。ここでは非常に端折った説明、さわりのさわりだけにとどめます。

 ASCII、JIS X 0201、JIS X 0208は、ISO 2022に準拠した文字コードです。また、ASCII、JIS X 0201、JIS X 0208をそれぞれ単独で使うぶんには、あとで述べるエスケープ シーケンスの仕組みを使う必要はありません。

 後で述べるISO-2022-JPもISO 2022に準拠した文字符号化方式の仕組みで、ISO 2022のエスケープ シーケンスの仕組みを使って文字コード表を切り替えることによって、ASCII、JIS X 0201(半角カナを除く)、JIS X 0208を切り替えて使えます。

 ISO 2022はエスケープ シーケンスによる文字コード表の切り替えだけでなく、シフトコードSO(0x0E)、SO(0x0F)による面の切り替えも規格化しています。JIS X 0201の7ビットコードは、この仕組みを使ったものです。

 もう1つ、ISO 2022に準拠した文字コードにEUC-JPがあります。これはいわゆる半角カナを使うためにSS2(0x8E)、JIS X 0212の文字集合(補助漢字)を使うためにSS3(0x8F)というシングルシフトコードを使います。

 JIS X 0201の7ビットコードで使われるシフトコードは、SOからSIまでずーっとシフト状態(右面カナ状態)になります。
 一方EUC-JPで使われるシングルシフトコードは、各文字の先頭にシフトコードを付けます。EUC-JPのJIS X 0201カナは、すべての文字の先頭に0x8Eがつくので、結果的に0x8E+JIS X 0201カナという2バイトコードになります。また、補助漢字は0x8F+JIS X 0212の漢字コードになるので、結果的に3バイトコードになります。各文字ごとにシフトして元の状態に戻っているわけです。
 SO〜SIのシフト方式は、面切り替えによって増える制御文字が少なくて済みますが、文字が状態を持つことになります。
 一方シングルシフト(SS)方式は、各文字がシフトするので文字が状態を持つことはありませんが、制御文字が文字数分入って、信号量がぐっと増えます。

 このようにISO 2022はさまざまな文字コード方式を許容する柔軟な仕組みですが、結果的に、その全体は超・複雑な仕組みになっており、ASCII、JIS X 0201、JIS X 0208、ISO-2022-JP、EUC-JPといったISO 2022に準拠する文字コードも、すべてそのサブセット(一部だけの実装)となっています。

ISO-2022-JP

 このISO 2022の仕組みを使って、日本語を7ビットで送ることを目的にした仕組みがISO-2022-JPです。ISOと2022の間にハイフンが入ります。ISO-2022-JPもISO 2022のサブセットで、ISOが提唱した仕組みでもありませんので注意して下さい。また、JISコードと呼ばれることもありますがJISが提唱したコードでもありません。ややこしいわ!
 これは、ISO 2022のエスケープシーケンスの仕組みを使って、ASCII、JIS X 0201(ローマ字部分のみ)、JIS X 0208を切り替えます。

 いま、Mac上のCotEditorでISO-2022-JPのファイルを作ります。
 テキストの内容は

abcアイ(改行)
亜伊012(改行)

です。
09
 これをhexdumpコマンドでダンプしました。
24
 わかりやすく文字とコードを並べてみます。

a  b c Esc $  B  ア   イ   Esc $  ( (改行)
61 62 63 1B 24 42 25 22 25 24 1B 28 42 0A

Esc $  B  亜   伊   Esc $  (  0  1  2 (改行)
1B 24 42 30 21 30 4B 1B 28 42 30 31 32 0A

 まず、ASCII文字のabc(0x61 62 63)が来ます。

 次にEsc $ Bというのが来ます。Esc(0x1B)は制御文字で、次が$(0x24)、B(42)です。これがエスケープシーケンスで、これからJIS X 0208:1983を呼び出すよーという合図です。ここでコード表が切り替わります。
 ご紹介が遅れましたがエスケープシーケンスとは、Esc(0x1B)で始まる文字列という意味です。エスケープシーケンスと呼び出す文字コードの関係はISOに登録されています。

 次にア、イが来ます。これはJIS X 0208でエンコードされていて、それぞれ0x2522、0x2524です。(全角カタカナはァアィイゥウ…という順番になっているのでアとイは1個飛びます)

 次にEsc $ ((0x1B 28 42)が来ます。これはASCIIを呼び出すよーという合図です。で、1行目の最後が0x0Aです。これは(Mac/UNIXの)改行の制御文字です。

 最初にabcが来た時、なぜEsc $ (が来なかったのでしょうか。これは行の先頭はASCIIまたはJISラテン文字と仮定するというISO-2022-JPの仕組みによるものです。
 また、JIS X 0208も改行は0x0Aですが、これは改行の前およびデータの末尾では必ずASCIIまたはJISラテン文字に戻すというISO-2022-JPの仕組みによるものです。
 この2つの仮定によって、行の最初は必ずASCIIまたはJISラテン文字にリセットされているので、何行にも渡って文字化けしっぱなしという事態を避けることができます。

 次の行の冒頭に、JIS X 0208の開始を示すEsc $ Bが来ます。で、亜(0x3021)、伊(0x304B)というJIS X 0208漢字が来ます。

 で、Esc $ (が来るので次がASCIIと分かります。で、数字の012(0x30 31 32)が来ます。最後が改行(0x0A)ですが、ここまでASCIIでしたのでエスケープシーケンスの必要はありません。

 このように、エスケープシーケンスを使ってコード表を切り替えることでASCIIとJIS X 0208を混在できています。なお、他にJIS X 0201ローマ字(エスケープシーケンスはEsc ( J)、JIS X 0208:1978(エスケープシーケンスはEsc $ @)も使えます。

 エスケープシーケンスはISO 2022の決まりですが、ISO 2022に準拠している文字コードがすべてエスケープシーケンスを使うというわけではありません。ASCIIやJIS X 0201 8ビットコード、JIS X 0208を単独で使う場合は文字コード表が1つですのでエスケープシーケンスを使いませんし、JIS X 0201 7ビットコードはSO/SI、EUC-JPはシングルシフトで文字ごとに文字コード表を切り替えるのでやはりエスケープシーケンスを使いません。

 一方、このあと紹介するISO-2022-JPは(名前が似ているのでややこしいですがISOの後にハイフンがつくので注意)エスケープシーケンスを使って文字コード表を切り替えます。JIS X 0201の8ビットコードや、シングルシフトコードは使いません。

ISO-2022-JPと半角カナ

 ISO-2022-JPはすべて7ビットコード(0x80未満)で、ASCII前提で作られた古いネット環境と相性が良く、Unicodeの時代になるまではインターネットの標準的な文字コードでした。ISO-2022-JPでは半角カナ(JIS X 0201の右面)は使えません。これが、昔のインターネットの人が言う「半角カナをネットで使ってはダメだ」という言い分の根拠です。

 ただ、使う人は使うので、多くの電子メールクライアントなどでは私的拡張で半角カナが使えました。ISO 2022のエスケープシーケンスEsc ( I(0x1B 28 49)のあとは半角カナ(Microsoft Outlook方式)、JIS X 0201中にSOのあとは半角カナで、使ったらSIで戻す(IE3当時のInternet Mail方式)など、数々の私的拡張がありました。思いっきりJIS X 0201の8ビット符号(0xA1以降)を入れる形式もありました。使う人がいたから「使ってはダメ」とわざわざ言われたわけです。

符号化文字集合と文字符号化方式

 これまで文字と、それをエンコードしたコンピューターの中の数値の関係を総称して「文字コード」と言って来ましたが、文字コードには符号化文字集合(Coded Character Set=CCS)と文字符号化方式(Character Encodging System=CES)の2つがあります。

 符号化文字集合は文字の集まりを番号によって整理したもので、文字符号化方式は文字をコンピューター内部/ネット上の数値に変換する規則です。

 と、書くと同じような感じがします。実際ASCII、JIS X 0201、JIS X 0208は、他の文字コードに文字レパートリーを提供する符号化文字集合でもあり、それぞれ単独で使う場合は文字レパートリーを数値に変換する文字符号化方式という、2つの面を持っています。

 一方、ISO-2022-JPはASCII、JIS X 0201、JIS X 0208から文字レパートリーをもらってきて、その切り替えも含めて定義した文字符号化方式です。符号化文字集合ではありません。

 まだ詳細に紹介していないEUC-JPやShift_JISも、あくまで文字符号化方式であり、符号化文字集合ではありません。

 先走りますがUnicodeは、符号化文字集合(CCS)としてのUCSと、それを数値化する文字符号化方式(CES)としてのUTFを区別しています。
 Unicodeの符号化は、まずUTF-8/UTF-16/UTF-32を分ける文字符号化形式(Character Encoding Form=CEF)という段階があり、それをコンピューター内部でバイト化する(UTF-16をUTF-16(BOMつき)とUTF-16BEとUTF-16LEの3つに、UTF-32をUTF-32(BOMつき)とUTF-32BEとUTF-32LEの3つに分ける)バイト直列化(Byte Serialization)という段階を経て分かれたものを文字符号化スキーム(CES)と言うそうです(UTF-8の場合CEFとCESは同じだが便宜上分ける)。どうもそういうことみたいです。ひー難しい!

 今回ぜんぜんPerl登場してませんが、いったん項を区切ります。