コンピューター内部では、すべての情報が最終的にバイナリ文字列として表現されることがわかっています。各バイナリ ビットには 0 と 1 の 2 つの状態があるため、8 つのバイナリ ビットを組み合わせて 256 個の状態にすることができ、これをバイトと呼びます。つまり、1 バイトを使用して合計 256 の異なる状態を表すことができ、各状態は 0000000 から 11111111 までの 256 個のシンボルに対応します。
1960 年代に、米国は英語の文字とバイナリ ビットの関係を統一する一連の文字エンコーディングを策定しました。これは ASCII と呼ばれ、現在でも使用されています。
ASCII コードは、合計 128 文字のエンコーディングを指定します。たとえば、スペース「SPACE」は 32 (バイナリ 00100000)、大文字の A は 65 (バイナリ 01000001) です。これら 128 個のシンボル (印刷できない 32 個の制御シンボルを含む) はバイトの最後の 7 ビットのみを占め、最初のビットは一律に 0 に設定されます。
英語をエンコードするには 128 個のシンボルで十分ですが、他の言語を表すには 128 個のシンボルでは不十分です。たとえば、フランス語では、文字の上に発音記号がある場合、ASCII コードでは表現できません。その結果、ヨーロッパの一部の国は、バイト内のアイドル状態の最上位ビットを使用して新しいシンボルをエンコードすることを決定しました。たとえば、フランス語の é のエンコードは 130 (バイナリ 10000010) です。その結果、これらのヨーロッパ諸国で使用されているエンコード システムは、最大 256 個のシンボルを表現できます。
しかし、ここで新たな問題が発生します。国が異なればアルファベットも異なるため、たとえすべての国が 256 記号のエンコーディングを使用していても、それらが表す文字は異なります。たとえば、130 はフランス語のエンコードでは é を表し、ヘブライ語のエンコードでは文字 Gimel (ג) を表し、ロシア語のエンコードでは別の記号を表します。しかし、いずれにせよ、これらすべてのエンコード方法で、0 ~ 127 で表されるシンボルは同じであり、唯一の違いはセクション 128 ~ 255 です。
アジア諸国の文字に関しては、さらに多くの記号が使用されており、その数は 10 万字にも達します。 1 バイトは 256 個のシンボルしか表現できませんが、1 つのシンボルを表現するには複数のバイトを使用する必要があります。たとえば、簡体字中国語の一般的なエンコード方式は GB2312 で、中国語の文字を表すのに 2 バイトを使用するため、理論的には最大 256x256=65536 個の記号を表現できます。
中国語のエンコードの問題については特別な記事で説明する必要がありますが、このノートでは取り上げません。ここで指摘するのは、記号を表すために複数のバイトが使用されますが、GB クラスの中国語文字エンコーディングは、後の Unicode や UTF-8 とは何の関係もありません。
前節で述べたように、世界には多くの符号化方式があり、同じ 2 進数が異なる記号に解釈されることがあります。したがって、テキスト ファイルを開く場合は、そのエンコード方法を知っておく必要があり、間違ったエンコード方法で解釈すると文字化けが発生します。メールが頻繁に文字化けして見えるのはなぜですか? それは、送信者と受信者が異なるエンコード方法を使用しているためです。
世界中のすべての記号を含むコードが存在すると考えられます。それぞれの記号には固有のコードが与えられているため、文字化けの問題は解消されます。これは、その名前が示すように、すべての記号のエンコードである Unicode です。
Unicode はもちろん非常に大規模なコレクションであり、現在 100 万を超えるシンボルを保持できます。各記号のエンコードは異なります。たとえば、U+0639 はアラビア文字 Ain を表し、U+0041 は英語の大文字 A を表し、U+4E25 は中国語の文字「strict」を表します。特定の記号の対応表については、unicode.org または特殊な漢字対応表を確認できます。
Unicode はシンボルのバイナリ コードを指定するだけであり、その内容は指定しないことに注意してください。バイナリコードはどのように保存する必要があります。
たとえば、中国語の文字「strict」の Unicode は 16 進数 4E25 で、これは 15 桁の 2 進数 (100111000100101) に変換されます。これは、この記号の表現には少なくとも 2 が必要であることを意味します。バイト。他の大きなシンボルを表すには、3 バイトまたは 4 バイト、あるいはそれ以上のバイトが必要になる場合があります。
ここには 2 つの重大な問題があります。最初の質問は、Unicode と ASCII をどのように区別できるのでしょうか? 2 番目の質問は、3 つのバイトがそれぞれ 3 つのシンボルではなく 1 つのシンボルを表すということです。つまり、英語の文字を表現するには 1 バイトだけで十分であることがすでにわかっています。Unicode で各記号が 3 バイトまたは 4 バイトで表現されると統一的に規定されている場合、各英語文字の前には 2 文字または 3 文字が必要であり、これは 0 です。テキスト ファイルのサイズが 2 倍または 3 倍大きくなり、これは容認できないことです。
それらが引き起こす結果は次のとおりです: 1) Unicode の複数の保存方法が出現しました。これは、Unicode を表現するために使用できるさまざまなバイナリ形式が存在することを意味します。 2) Unicode は、インターネットが出現するまで長い間普及することができませんでした。
インターネットの普及により、統一されたエンコード方式の出現が強く求められています。 UTF-8 は、インターネット上で最も広く使用されている Unicode 実装です。他に UTF-16 や UTF-32 などの実装もありますが、これらは基本的にインターネットでは使用されません。繰り返しになりますが、ここでの関係は、UTF-8 が Unicode 実装の 1 つであるということです。
UTF-8 の最大の特徴の 1 つは、可変長エンコード方式であることです。シンボルを表すのに 1 ~ 4 バイトを使用でき、バイト長はシンボルによって異なります。
UTF-8 のエンコード規則は非常に単純で、次の 2 つだけです:
1) シングルバイト記号の場合、バイトの最初のビットは 0 に設定され、次のビットは 0 に設定されます。 7 ビットはこのシンボル用です。したがって、英語の文字の場合、UTF-8 エンコーディングと ASCII コードは同じです。
2) n バイトのシンボル (n>1) の場合、最初のバイトの最初の n ビットは 1 に設定され、n+1 番目のビットは 0 に設定され、次のバイトの最初の 2 ビットはバイトは 1 に設定されます。常に 10 に設定されます。言及されていない残りの 2 進ビットはすべて、このシンボルの Unicode コードです。
次の表はエンコード規則をまとめたもので、文字 x は利用可能なエンコード ビットを示します。
Unicode 記号範囲 | UTF-8 エンコード
(バイナリ)
------------- ---- ---+------------------------------------------------- - --
0000 0000-0000 0xxxxxxx
0000 0080-0000 07FF | 110xxxxxx
0000 0800-0000 FFFF | xxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
次に、UTF-8 エンコーディングを実装する方法を示すために、漢字「厳密」を例に挙げてみましょう。
strict の Unicode は 4E25 (100111000100101) であることが分かります。上記の表より、4E25 は 3 行目 (0000 0800-0000 FFFF) の範囲にあることがわかります。したがって、「厳密な」UTF-8 エンコーディングには 3 バイトが必要です。つまり、形式は「1110xxxx 10xxxxxx 10xxxxxx」です。次に、「strict」の最後の 2 進数から始めて、形式の x を後ろから前に埋め、余分なビットを 0 で埋めます。このようにして、「strict」の UTF-8 エンコーディングは「11100100 10111000 10100101」であることがわかり、16 進数に変換すると E4B8A5 になります。
前のセクションの例から、「strict」の Unicode コードは 4E25、UTF であることがわかります。 - 8 エンコーディングは E4B8A5 ですが、この 2 つは異なります。それらの間の変換はプログラムを通じて実現できます。
Windows プラットフォームでは、最も簡単な変換方法の 1 つは、組み込みのメモ帳アプレット Notepad.exe を使用することです。ファイルを開いた後、[ファイル] メニューの [名前を付けて保存] コマンドをクリックすると、ダイアログ ボックスが表示され、下部に [エンコーディング] ドロップダウン バーが表示されます。
内部には ANSI、Unicode、Unicode ビッグ エンディアン、UTF-8 の 4 つのオプションがあります。
1)ANSI がデフォルトのエンコードです。英語ファイルの場合は ASCII エンコード、簡体字中国語ファイルの場合は GB2312 エンコードです (Windows 簡体字中国語バージョンの場合のみ、繁体字中国語バージョンの場合は Big5 コードが使用されます)。
2) Unicode エンコードとは、2 バイトを直接使用して文字の Unicode コードを格納する UCS-2 エンコード方式を指します。このオプションはリトルエンディアン形式を使用します。
3) Unicode ビッグ エンディアン エンコードは前のオプションに対応します。リトルエンディアンとビッグエンディアンの意味については次の章で説明します。
4) UTF-8 エンコード。前のセクションで説明したエンコード方法です。
「エンコード方式」を選択後、「保存」ボタンをクリックすると、ファイルのエンコード方式がすぐに変換されます。
前のセクションで説明したように、Unicode コードは UCS-2 形式で直接保存できます。漢字「厳密」を例にとると、Unicode コードは 4E25 で、1 バイトが 4E、もう 1 バイトが 25 の 2 バイトで格納する必要があります。格納する場合、前に 4E、後ろに 25 が来るビッグエンディアン方式と、前に 25、後ろに 4E が来るリトルエンディアン方式です。
これら 2 つの奇妙な名前は、イギリスの作家スウィフトの「ガリバー旅行記」に由来しています。この本では、リリパットで内戦が勃発しました。戦争の原因は、ビッグエンディアンとリトルエンディアンのどちらから卵を割るかについての人々の論争でした。この事件により六度の戦争が勃発し、一人の皇帝が命を落とし、また一人の皇帝が王位を失った。
したがって、1 バイト目からが「ビッグエンディアン」、2 バイト目からが「リトルエンディアン」となります。
したがって、当然のことながら、次のような疑問が生じます: コンピュータは、特定のファイルがどの方法でエンコードされているかをどのようにして知るのでしょうか?
Unicode 仕様では、各ファイルが先頭に追加されると定義されています。エンコードシーケンスを表す文字。この文字の名前は「ZERO WIDTH NO-BREAK SPACE」で、FEFF で表されます。これはちょうど 2 バイトであり、FF は FE より 1 大きい値です。
テキスト ファイルの最初の 2 バイトが FE FF の場合は、ファイルがビッグエンド モードを使用していることを意味し、最初の 2 バイトが FF FE の場合は、ファイルがスモールエンド モードを使用していることを意味します。
以下に例を示します。
「メモ帳」プログラム Notepad.exe を開き、新しいテキスト ファイルを作成します。内容は「strict」という単語で、ANSI、Unicode、Unicode ビッグ エンディアン、および UTF-8 エンコードで保存します。
次に、テキスト編集ソフトウェア UltraEdit の「16 進関数」を使用して、ファイルの内部エンコーディングを観察します。
1) ANSI: ファイルのエンコードは 2 バイトの「D1 CF」で、これは「厳密な」GB2312 エンコードであり、GB2312 がビッグヘッド モードで保存されていることも意味します。
2) Unicode: エンコードは 4 バイト「FF FE 25 4E」です。「FF FE」はリトル エンディアン モードで格納されていることを示し、実際のエンコードは 4E25 です。
3) Unicode ビッグ エンディアン: エンコードは 4 バイトの「FE FF 4E 25」で、「FE FF」はビッグ エンディアン ストレージを示します。
4) UTF-8: エンコードは 6 バイト「EF BB BF E4 B8 A5」です。最初の 3 バイト「EF BB BF」はこれが UTF-8 エンコードであることを示し、最後の 3 バイト「E4B8A5」は" "厳密な" 特定のエンコーディング。その格納順序はエンコーディング順序と一致します。