コンピュータの世界の「文字」

コンピュータ上の文字

コンピュータは常に、扱うことができるのは「数」です。 そのため、コンピュータは直接に文字を扱うことができません。

コンピュータが文字を扱うためには

という3つの要素が必要となります (実際にはより多くの要素が必要ですが、ここで知る必要があるのはこれだけです)。

文字集合

私達人間は、なんとなく知っている曖昧な情報を利用することができますが、コンピュータにおいては齟齬があってはいけません。 そこで、コンピュータで文字を利用するために、コンピュータが取り扱う文字を明確に決める必要があります。

この、「どのような文字があるか」ということを定めたのが文字集合です。

事実上、最も基本となっている文字集合はASCIIというものです。 これはアメリカで制定され、英語アルファベットと数字、そして少しの記号を含めて127文字が定義されています。

この127文字のうち、目で見ることができるのは93文字です。 これ以外の34文字は、スペース記号を含め、目に見えない特殊な文字となっています。

もちろん、この中に日本語は含まれていません。 そのため、各国で自国の文字を含む独自の文字集合が作られました。

日本語の文字集合で広く使われているのは、JISによって制定された、JIS X0201, JIS X0208, JIS X0212, JIS X0213です。 JIS X0201には「半角カナ」だけが含まれており、JIS X0208に基本的な「全角文字」が含まれています。

JIS X0212及びJIS X0213は、人名漢字の不足などを補強し、旧字体などにも対応します。

これ以外で、現在使われることはまずない日本語文字集合としては、今昔文字鏡やTRONコードなどがあります。

文字エンコーディング

コンピュータの世界では「8ビット = 1バイト がひと組」というルールがあります。 8ビットで表せる数の最大は255で、これよりも小さい数でいいのであれば、数をそのまま文字に変換することができます。

実際に、ASCIIコードや、西ヨーロッパの文字集合(アクセント付きアルファベット、例えばèなどを含むもの)などは単純な数で表現されています。

また、JIS X0201は半角カナを付け足して255文字以内に収まっていますから、これも同様です。 ところが、JIS X0208は6879文字を含みますので、到底この方法では表すことができません。

このことから、「どんなふうに膨大の文字を数で表現するか」という方法が必要になります。 この「方法」が文字エンコーディングです。

日本語で使われる主たる文字エンコーディングは次の3つです。

ISO-2022-JP及びEUC-JPは標準化された国際的な枠組みに従った日本語の表現方法です。 対して、Shift_JISは完全に独特な方法で表現します。

もっとも広く使われたのはShift_JISです。 この大きな要因は、Windowsが標準の日本語文字エンコーディングとしてShift_JISをベースにしたものを採用したことでしょう。

ただし、これは他の名前で呼ばれるもの(Windows-31J, MS932, CP932, MSCP932, MS漢字コード, OEM CP 932)であり、完全に同一ではありません。このため、「Windows上でしか読めない文字がある」あるいは「Windows以外とは違う文字になる」という状態が存在しました。

JIS X0212及びJIS X0213はISO-2022-JPでは表現できません。 これらを表現するには、規格に違反した独自の拡張を行ったものを使用するか、新しいShift_JISまたはEUC-JPを使用する必要があります。

Windows, MacともにShift_JISをベースにしたものを使用していましたが、Unix系システムではEUC-JPが一般的でした。 また、インターネット上での情報交換(例えばメール)などはISO-2022-JPが使用され、古いウェブサイトなどではISO-2022-JPで書かれているものもあります。

フォント

文字集合と文字エンコーディングは「数で文字を表す」ことです。

例えば

「これはShift_JISで書かれていて、21392だから、「31区20点 心」だね」

ということはわかるのですが、この時点でそれが「どんな形をしているか」というのはわからないのです。 そのため、これを文字としてその形を見ることができません。

この「規格で決められた文字」に形を与えるのが「フォント」です。

基本的には、コンピュータの規格では存在していないにしても、「心という字」といえばだいたいイメージはつきますし、形もわかるでしょう。 ところが、ひとの認識は割と曖昧で、かなり大胆に形が違ったとしてもちゃんと読めてしまいます。 つまり、文字の形にはデザインの余地が大いにあり、規格で厳密に固定する必要がありません。

例えば「心」という文字は、フォントでは多くの場合1つ目の点を文字の上に書きます。 しかし、手書きの場合は右に書くのが一般的です。そして、どちらでも文字としては正しく認識できます。

このことからフォントは文字に対して厳密に決められているわけではありません。どのような形で見せるか、というのは、デザインを含めたフォントによって最終的に決められていると言えます。

また、文字を形として見せるためにはフォントが必要ですから、コンピュータ的には表現できている文字であっても、フォントのデータがないとその文字を表示することができません。

さらに特殊な用法として、「文字がなにを表しているかという規定を無視したフォント」というのもあります。 例えばASCIIだと見える文字は93文字しかありませんが、シンボルフォントと呼ばれるものは、ABC…といった普通の文字に対応したフォントを、♡などの記号にしています。 これを利用して、実際にはABC…といった普通の文字で書いているのですが、記号にしたい部分だけシンボルフォントにすることで文字集合には存在しない記号が表現できる、というわけです。

外字

コンピュータにおける外字は、「文字エンコーディング的には表現できるけれど、文字集合としてそこに文字はなにもない」という状態になっているものに、規格にない文字を定義するしたものです。

例えばJIS X0208は空間としては8836個のマスがある状態になっており、このうち文字があるのは6879個です。 つまり、1957個は何も決められていない、空の状態になっています。

ここに、独自の文字があることにします。独自ですから規格としての意味は成り立ちませんので、フォント側で規格外の文字に対応することになります。

これは交換性がありません。文字を表示するためにはフォントが必要であり、フォントは規格に基づいていますから、独自の文字を定義しても「他のひとは知らない」という状態になってしまいます。

現実的な外字の利用目的は、あくまで手元での表示、あるいは印刷に限られます。

ただし、一部には「正規の規格にはないものの、追加された外字が拡張規格として成立している」というものがあります。 Windowsで採用されているCP932エンコーディングは純粋にJIS X0208に対応しているわけではなく、さらに外字を追加したものに対応しており、 これはWindowsにおいて広く使用できることから、限定的ながら普及し、通用するものになります。

Unicode

こういった形で各国ローカルに定義されてきた「コンピュータ上での文字」ですが、これでは言語による国境ができてしまいます。 例えばひとつの文書の中に日本語と韓国語を混ぜたり、タイ語と中国語を混ぜたりすることができません。

こうした問題を解決する、「世界の言葉の文字集合」がUnicodeです。

Unicodeを使うと今まで一緒にすることのできなかった色々な文字を使うことができるようになりましたし、様々な絵文字😁✬✨も使うことができるようになりました。

Unicodeは日本語文字集合とは全く別のものであり、JIS X0208などとは互換性がありません。 ただし、JIS X0201, JIS X0208, JIS X0213に含まれているほとんどの文字はUnicodeにも採用されていますから、基本的に「使えなくなる文字」というのはありません。ただ、別物であるというだけです。

Unicodeを表現するエンコーディングには、UCS-2, UTF-8, UTF-16LE/BE, UTF-32LE/BEなどがあります。 現在は世界的にUTF-8に統一する方向になってきています。

「世界の言葉」の考え方

全角、半角

全角、半角というのはJISで定義された、日本独自のものです。 ですから、JIS文字集合にはこの概念がありますが、Unicodeにはありません。

そのかわり、アルファベットのような文字をnarrow width、日本語などアルファベットよりも明確に広い幅を持つ文字をwide widthと定義しています。

記号の中で、日本語の文字集合に含まれていた(全角だった)一方で、他の国の文字集合にも含まれていた(narrowだった)ようなものは、 ambiguous widthとして、narrowとするかwideとするかは場合による、という扱いになっています。

「ambiguous widthな文字を常にwide characterとして扱う」という設定がある場合、従来の感覚に近づきますが、これはそのように振る舞うことができるフォントである必要があります。

と、ここまでは簡略化した説明で正しい説明ではありません。 ここからはより難しい、正しい説明です。

これらはEast Asian Width(EAW)という概念にあり、幅広の文字を必要とする東アジア(要は日本のほか、中国、韓国)向けに特別な文字幅の定義がされています。

まず、半角が普通な文字に対する全角(例えば、全角英数)を意味するfullwidth、全角が普通な文字に対する半角(半角カナなど)を意味するhalfwidthです。

で、fullwidthではないけれど全角な文字がwide、halfwidthではないけれど半角な文字がnarrowです。

つまり対応関係は、narrowとfullwidth、wideとhalfwidthになります。

ambiguousは日本語の文字集合にも、日本語以外の文字集合にもあって、日本語で全角/半角の別がない文字です。 記号以外にも、キリル文字やギリシャ文字なども含まれています。これらはネイティブな文字集合では幅広ではありません。

そして、これらの東アジア文字集合にない文字はneutralとなっています。ヘブライ語とかですね。これは、東アジアのこの概念で感知しないということです。

日本語文字集合にあった日本語ではない文字

こうした中でambiguousな文字はちょっと困ることがあります。

基本的には「フォントや設定やアプリによって幅が変わる」という話なのですが、もっと困るのは縦書きのときです。

縦書きの半角文字というのは、寝かせて書く、というのが普通です。 ではambiguousな文字はどうなるのでしょう。

答えは文脈による、です。

国際的な文字集合のおかげで、「国産アプリでないと日本語が使えない」みたいなことがなくなって自由度はとても上がったのですが、 アプリによってはambiguousな文字を縦書きすると半角扱いになる、といった問題があったりします。

このあたりは日本語の都合だけで考えずに、世界的にその文字はどうなのか、ということを考える必要があります。 壁をなくすためには歩み寄りも必要です。

おまけ。「2バイト文字」

全角文字を表す別の言い方として「2バイト文字」というものがありました。

これは2つの側面があり、ひとつはJIS X0201は計256文字に収まり、1バイト(=8ビット)に収まっていたのに対し、JIS X0208はこれを越えるため、単純にJIS X0208の文字(原則すべて全角)を「2バイト文字」と表現することです。

もうひとつは、Shift_JISにおける表現です。Shift_JISはJIS X0201バイト列と共存させるために、複雑に移動させ詰め込んだ非常に難しい表現方法を持つ文字エンコーディングです。 これはJIS X0201を1バイト領域とした形のまま避けているため、JIS X0208=全角=2バイト文字の図式を維持できます。

なお、EUC-JPではひらがなは1バイトで表されますから、日本語文字エンコーディングだからといって必ずしも「全角=2バイト」というわけではありません。

ところが、Unicodeのエンコーディングではそうはなっていません。 UTF-16では2バイトまたは4バイト、UTF-32では4バイト固定、UTF-8では1バイトから6バイトです。

結果的にテキストの容量と、文字の幅、そして文字種は全く相関がないのが実情であり、かつては便宜的な表現として通用した「2バイト文字」という表現も、現在は混乱をもたらすだけです。

ちなみに、ファイル容量、ということで言えば、Shift_JISからUTF-8に変更するとほとんどの場合増えます。