こういった問題に対処するには、文字コードに関する体系的な理解が必要となります。
なお、この連載では、とっつきにくさを避けるため、最初のうちは未定義の用語や必ずしも厳密でない説明を用いることがありますので、正しい理解のためには必ず最後まで読んでください。(^_^)
制御コード | 0x00〜0x1F、0x7F |
---|---|
ASCII文字 | 0x20〜0x7E |
カタカナ | 0x21〜0x5F (7ビット) / 0xA1〜0xDF (8ビット) |
漢字 | 0x2121〜0x7E7E (第1バイト・第2バイトとも0x21〜0x7E) |
補助漢字 | 0x2121〜0x7E7E (第1バイト・第2バイトとも0x21〜0x7E) |
ASCIIとカタカナを基本とし、漢字が追加されています。ASCIIと漢字のコード範囲が重複するため、以下のようなエスケープシーケンスによって切り替えます。
漢字の開始 | ESC $ @ または ESC $ B |
---|---|
ASCIIの開始 | ESC ( B または ESC ( J |
補助漢字を含めることも可能であり、補助漢字の開始のシーケンスは ESC $ ( D となります。
また、7ビットの環境では、カタカナもこれらと重複するため、制御コードまたはエスケープシーケンスで切り替えます。
カタカナの開始 | SO (0x0E) または ESC ( I |
---|---|
ASCIIの開始 | SI (0x0F) または ESC ( B または ESC ( J |
このようにカタカナも7ビットで表現するものを俗に7ビットJISと呼び、これに対してカタカナを8ビットで表現するものを俗に8ビットJISと呼びます。
JISコードの利点の一つは、7ビットの通信路でも伝送できることです。未だに7ビットの伝送路が少なくないインターネットの世界で使われている理由もここにあります。しかし、エスケープシーケンスの存在が厄介ですので、コンピュータ内部のデータ処理ではあまり使われません。
なお、98のN88日本語BASICや、PC-PR系プリンタなどでも同様のコードが使われていますが、エスケープシーケンスが "ESC K" と "ESC H" という独自のものになっています。これは通称NEC JISと呼びます。
制御コード | 0x00〜0x1F、0x7F |
---|---|
ASCII文字 | 0x20〜0x7E |
カタカナ | 0xA1〜0xDF |
漢字 | 0x8140〜0x9FFC、0xE040〜0xFCFC (第1バイト: 0x81〜0x9F、0xE0〜0xFC 第2バイト: 0x40〜0x7E、0x80〜0xFC) |
8ビットパソコンで広く使われていたASCIIとカタカナをそのまま継承し、なおかつJISコードのようなエスケープシーケンスを使わずに漢字を混在させるために、所定の計算式によってJIS漢字コードを変換しています。
漢字の第1バイトはASCIIやカタカナと重複しないように配置されており、第1バイトを見ただけで文字種がわかるようになっています。漢字の第2バイトについても、区切り文字として使われることの多いASCIIの0x20〜0x3Fや、制御コードである0x7Fと重複しないようになっています。また、画面上ではASCIIやカタカナと漢字の幅の比率は1:2であることが多いですが、文字コードのバイト数もこれと同じく1:2になっています。このような特長のため、特別にシフトJISに対応していないシステム上でもなんとか日本語を通せる場合が少なくありません。
欠点としては、コード空間に余裕が少なく拡張性に乏しい(例えば、補助漢字を入れるスペースがない)こと、第2バイトに含まれる0x40〜0x7Eのコード(特に、ASCIIのバックスラッシュにあたる0x5C)が問題となる場合があること、MSBが落ちたときの復元が困難なこと、などがあげられます。
制御コード | 0x00〜0x1F、0x7F |
---|---|
ASCII文字 | 0x20〜0x7E |
漢字 | 0xA1A1〜0xFEFE (第1バイト・第2バイトとも0xA1〜0xFE) |
カタカナ | 0x8EA1〜0x8EDF |
補助漢字 | 0x8FA1A1〜0x8FFEFE (第2バイト・第3バイトとも0xA1〜0xFE) |
JISやシフトJISとの大きな相違点は、カタカナが冷遇されていることです。JIS漢字コードの各バイトのMSBを1にすることにより漢字を導入したため、これと重複するカタカナは補助的な扱いとなり、0x8Eのプレフィクス付きの2バイトコードになっています。また、0x8Fのプレフィクスにより補助漢字も表現でき、これは3バイトになります。
特長としては、エスケープシーケンスがない、第1バイトを見ただけで文字種がわかる、漢字の第2バイトがASCIIと重複しない、ASCIIと漢字のバイト数の比率が文字の幅と一致する、などシフトJISと類似した点に加えて、JISとのコード変換が容易なことがあげられます。
ただし、バイト数はカタカナや補助漢字まで考慮すると複雑となります。事実、EUCを採用したシステムでも、補助漢字までサポートしている例は非常に少なく、カタカナのサポートもつい最近まではなおざりにされてきました。日本のインターネット上では、今に至るまでカタカナの使用がタブーとされていますが、これは、EUCを採用しながらカタカナをサポートしていないシステムが多かったためでもあります。
他の欠点としては、シフトJISよりマシとはいえ拡張性に限界があること、結果的にシフトJISと似て非なるものとなってしまい日本語コードの混乱を助長してしまったこと、などです。
0x00〜0x1F | 制御文字(control characters) |
---|---|
0x20 | 空白(SP) |
0x21〜0x7E | 図形文字(graphic characters) |
0x7F | 制御文字DEL(delete) |
制御文字とはいわゆるコントロールコードのことです。図形文字というと●とか▲とかハートマークとか罫線とかを思い浮かべるかもしれませんが、そうではなくて、アルファベット・数字・記号などの「目に見える形をもった」普通の文字のことです。空白は制御文字とも図形文字ともみなすことができます。個々の制御文字や図形文字の詳細については割愛しますが、図形文字で特に注意を要するのは次のコードです。
0x5C | バックスラッシュ「\」 | (≠円記号) |
---|---|---|
0x7C | 縦棒「|」 | (≠破線) |
0x7E | チルダ「〜」 | (≠オーバーライン) |
ASCIIはあくまで7ビットですので、0x80〜0xFFは含まれません。パソコンのマニュアルなどを見ると、0x80〜0xFFにカタカナやら何やらが入ったものを「ASCIIコード表」と称していることが多いですが、これはまちがいです。
余談ですが、制御文字の中でDELだけ0x7Fなんていうところに飛ばされているのはなぜでしょうか? これは、データ入力媒体として紙テープを使っていたころの名残だといわれています。紙テープでは、所定の位置に穴を空けてあるかどうかによって2進数の1/0を区別します(SunOSのppt(6)を参照)。1文字は7ビットですから、7つの位置の穴の有無で1文字を表します。で、もし穴を空けるときにまちがってしまった場合、穴をふさぐのは面倒ですので、そのまちがいを含む7ビット分全部の穴を空けて「この字はまちがいだから削除ね」ということにしていました。つまり、「削除」→「全ビット1」→「0x7F」というわけです。
文字コードに関してもISO規格は中心的役割を担っています。まずはISO 646という規格の登場です。これは、もともとアメリカ/英語用の規格であるASCIIを、他の国/言語用に一部変更できるようにしたものです。サンプルとしてIRV(International Reference Version)というものを用意しておき、これを各国が自国の規格として採用するとき、その中の一部のコードに関しては違う文字を割り当ててもよい、というふうになっています。実際にはIRVはASCIIと同じものです(数年前までは違っていた)。
IRVのうち、文字の割り当てを変更することが認められているコードは次の12個です。参考として、IRV(ASCII)で割り当てられている文字を併記します。
0x23 | # | 0x5C | \ | 0x7B | { |
---|---|---|---|---|---|
0x24 | $ | 0x5D | ] | 0x7C | | |
0x40 | @ | 0x5E | ^ | 0x7D | } |
0x5B | [ | 0x60 | ` | 0x7E | 〜 |
ISO 646のアメリカ版すなわちASCIIでは、これらの文字はそのままですが、ISO 646の各国版を見てみると、これらのコードに割り当てられている文字がそれぞれ違っています。例えば、ヨーロッパの多くの言語では、アクセント記号付きの文字が必要なので、それらをここに割り当てています。また、これだけでは足りない場合は、制御文字BS(backspace)を使い、合成文字として表現することを認めています。例えば、aに^を付けたものを表現する場合は、^ BS a となります。
ISO 646の日本版は、IRVの0x5Cを円記号に、0x7Eをオーバーラインにしたものです。これはJIS X 0201というJIS規格になっており、JISローマ文字集合(JIS Roman)と呼ばれています。国産のコンピュータはたいていこれを採用しているため、0x5Cが円記号に、0x7Eがオーバーラインになっているというわけです。ただし、NECのPCシリーズとその互換機に関しては、0x7EはIRVと同じチルダになっており、0x7CはIRVともJIS X 0201とも違う「破線」になっています。この結果、PCシリーズの0x21〜0x7Eの図形文字集合は、ISO 646のどの版とも一致しない独自のものになっています(ついでに言うと、古いマシンでは0x60が空白になっている)。
ところで、シリアルプリンタを持っている人は、マニュアルのディップスイッチの項を見てください。「各国文字の選択」という設定で、日本・アメリカ・イギリス・ドイツ・スウェーデンなどの選択肢があると思います。これはまさしくISO 646の各国版を切り替えていることに他なりません。
ISO 646のこのような仕組みは、コンピュータのメモリや通信路が限られていた時代に、7ビットという狭いコード空間でなんとかやりくりするためのものだったわけですが、当然の結果として、同じコードでも各国版によって表現する文字が違ってしまうという問題があります。JIS X 0201におけるバックスラッシュと円記号の違いはみなさんもご存じの通りです。
しかし、日本ではその程度ですからまだ我慢できますが、上記のコードにアクセント記号付きアルファベットなどを割り当ててしまった国ではそれどころではありません。特にCやUNIXでは上記の記号を多用しますが、これらがすべて「u-ウムラウト」やら「e-アクサンテギュ」やらになってしまっているのです。これではとてもCやUNIXを使ってはいられません(この問題に熱心なのはデンマークで、これらの記号を使わずにCを記述するための代用記法トライグラフを提唱しています)。
最近は、ASCIIをもとにしたISO 8859-1(後述)などの8ビットコードを使えるシステムが一般化したため、7ビットでしかも一国でしか通用しないISO 646各国版にこだわる必要もなくなってきました。そのため、ISO 646各国版は(日本を除いて)流行らなくなりつつあり、ASCIIをそのまま使うケースが多くなっています。
一方、欧米のコンピュータでも、ASCIIを8ビットに拡張して、そこにアクセント記号付きアルファベットや罫線を入れるようになりました。
パソコンの世界では、IBM PCの普及にともなってPCのコードが有力になりました。DOSのマニュアルにあるコードページ437、WindowsにおけるOEMコードセットというコードです。これの右半分には、アクセント記号つきラテンアルファベット・罫線・各種記号が入っています。しかし、言語によってはこれでも不十分なので、EGAやVGAでは右半分がPCG(死語:-))になっており、ここのフォントを入れ換えることができるようになっています。こうして、IBM PCのコードにはコードページと呼ばれるいくつもの変種ができました。これらもDOSのマニュアルに載っています。なお、MacintoshはIBM PCとはまた違った拡張コードを持っています。
コードページ | 名称(言語) | 文字種 |
---|---|---|
437 | IBM PC基本 | ラテン文字 |
850 | 多言語(西欧諸語) | ラテン文字 |
852 | スラブ(東欧)語 | ラテン文字 |
857 | トルコ語 | ラテン文字 |
860 | ポルトガル語 | ラテン文字 |
861 | アイスランド語 | ラテン文字 |
863 | カナダフランス語 | ラテン文字 |
865 | 北欧語 | ラテン文字 |
869 | ギリシア語 | ギリシア文字 |
932 | 日本語 | カタカナ(JIS X 0201) |
また、ISOでもASCIIをベースとした8ビットコードの規格をいくつか制定しました。その中でも有力なものが、ISO 8859という規格です。これもIBM PC同様、ASCIIを左半分に持ついくつもの変種(現在10個)からなっています。
ISO 8859-1 | (Latin-1) | ラテン文字 | 西欧諸語 |
---|---|---|---|
ISO 8859-2 | (Latin-2) | ラテン文字 | 東欧諸語 |
ISO 8859-3 | (Latin-3) | ラテン文字 | エスペラントなど |
ISO 8859-4 | (Latin-4) | ラテン文字 | |
ISO 8859-5 | キリル文字 | ロシア語など | |
ISO 8859-6 | アラビア文字 | アラビア語 | |
ISO 8859-7 | ギリシア文字 | ギリシア語 | |
ISO 8859-8 | ヘブライ文字 | ヘブライ語 | |
ISO 8859-9 | (Latin-5) | ラテン文字 | トルコ語など |
ISO 8859-10 | (Latin-6) | ラテン文字 | 北欧語など |
このうちISO 8859-1、通称Latin-1が広く使われています。ワークステーションのコンソール画面やxtermなどで8ビットコードを表示させると出てくるのが、このLatin-1です。また、Windowsも「ANSIキャラクタセット」という名前でLatin-1を正式採用しました。それ以外のISO 8859シリーズは、一応国際規格ではありますが、それぞれの言語のコミュニティの外ではあまり目にすることはありません。
IBMの各コードページやISO 8859のそれぞれは、ISO 646よりもずっと多くの文字を含んでいますので、適用範囲も広く、一つのコード表を複数の国・言語で共通に使うことが可能です。たとえば、Latin-1だけで英語・ドイツ語・フランス語など西欧の主要言語をカバーすることができます。
しかしまた、ラテン文字のコード表がいくつもあることに気がつくでしょう。これは、アクセント記号付きラテン文字の種類が多すぎて、一つのコード表に入り切れなかった結果です。また、ギリシア文字のようなまったく異なる文字を入れる余地もないので、これまた別のコード表になっています。どうしても混在させたければコード表を切り替えるしかありません。この問題は、8ビットというコード空間が本質的に狭すぎるのが原因であり、複数の国や言語で共通に使えるとはいっても、その範囲は自ずから限られてしまいます。
とくに8859の場合、当初の目標では、646各国版のようなわずらわしさを避けるために、コード空間を広げた代わりに合成文字を廃止して8ビット固定長にしたのですが、結局は似て非なるコード表がいくつもできてしまい、言語によって切り替えて使わなくてはならないという、646とたいして変わらない状況に陥ってしまいました。
なお、ISOの8ビットコード(8859に限らず)は、次のような構成になっています。
0x00〜0x1F | 制御文字の領域 |
---|---|
0x20〜0x7E | ASCII図形文字 |
0x7F | 制御文字DEL |
0x80〜0x9F | 制御文字の領域 |
0xA0〜0xFF | 追加の図形文字 |
つまり、右半分にも左半分同様に制御文字の領域があるということです。これについてはISO 2022の解説に譲ります。