文字エンコーディングの概要

UTF-16

UTF-16は16ビット可変長エンコードスキームであり、文字コードポイントにUTF文字セットを使用します。 これは、UTF-16でエンコードされた文字が16ビットのコード単位を持つことを意味します。UTF-8でエンコードされた文字は1から4のコード単位で表現できることがわかっているので、UTF-16文字は1または2のコード単位で表現できます。

UTF-8でエンコードされた文字は1から4のコード単位で表すことができます。 したがって、UTF-16文字は、そのコードポイントに基づいて16ビットまたは32ビットのメモリを取ることができます。

UTF-16エンコーディング仕様に飛び込む前に、UTF-16をどのように機能させることができるかを理解しましょう。

16ビットのコード単位を持っているので、理論的には、コードポイント0から65,535までの21文字をエンコードすることができます。 しかし、コードポイントが65,535より大きい文字がある場合はどうなりますか? その場合、別のコード単位を追加できます。しかし、問題は、UTF-16デコーダが文字をデコードするために2つのコード単位を考慮する必要があることをどのように知っているかということです。UTF-8は、最初のコード単位と継続コード単位の初期ビットを、UTF-8デコーダが文字が取ることができるコード単位の数を差し引くために使用できる特定のビッUTF-16コードユニットでも同じことができますが、この機能のためにコードユニット内のいくつかのビットを犠牲にする必要があります。

コード単位のいくつかの初期ビットを、UTF-16デコーダが理解できる意味のある値に設定することができます。

また、コード単位に自己同期力を与えるためには、コード単位は、それが最初のコード単位であるか継続コード単位であり、ただ一つのコード単位の文字ではないかどうかを知ることができなければならない。

そのため、Unicodeはコード単位の最初の6ビットを犠牲にして、コード単位ごとに文字のコードポイントをエンコードするために10ビットだけを残すことにし 文字が2つのコード単位を必要とする場合、メモリの20ビット(32ビットまたは4バイトのうち)には、文字の実際のコードポイント情報が含まれます。では、これらの初期ビットは何ですか、そしてこれらのビットがUTF文字セットでどのように凹みを作るのですか? 以下の例に従ってみましょう。UTF-16標準から、最初のコード単位は110110₂で始まり、2番目のコード単位は110111₂で始まる必要があります。 これは、UTF-16デコーダが最初のコードユニットと2番目のコードユニットのどちらかを理解するのに役立ちます。 これにより、UTF-16は自己同期化されます。

今、私たちは遊ぶためにコード単位ごとに10ビットを持っているもの、私たちは内で再生することができます範囲は何ですか? 最後に、どのように多くの文字は、UTF-16エンコードの二つのコード単位でエンコードすることができますか?

心配しないで、一つのコード単位でエンコードされた文字について話します。上記のコード単位テンプレートを見ると、1101 1000 0000 0000₂から1101 1111 1111 1111.の範囲があります。 これはD800₁₆からdfff₁₆に相当します。💡最初のコードユニットの範囲はD800₁₆から6FFF₁₆で、2番目のコードユニットの範囲はdc00₁₆からDFFF₁₆です。 これらの値は、すべてのコードポイントビットをオンとオフにすることで取得できます。UTF-16は自己同期でなければならないため、D800₁₆とdfff₁₆の間のコードポイントはutf-16の文字を表してはなりません。 すべてのUTFエンコーディングは同じUTF文字セットに従うため、これらのコードポイントはUTFによって制限され、文字⁰には割り当てられません。

D800₁₆とdfff₁₆の間のコードポイントは文字を表していないため、サロゲートコードポイントと呼ばれるか、一緒にサロゲートペア⁰とも呼ばれます。

最初のサロゲートコードポイント(最初のコードユニットから)は高サロゲートとも呼ばれ、第二のコードポイント(第二のコードユニットから)は低サロゲートとも呼ばれます。 2048コードポイント、サロゲートあたり1024の合計を作ります。

surサロゲートコードポイントは、2つのコード単位でより多くの文字をエンコードできるように、命を犠牲にしました。 それについて考えてみてください!大きな問題は、UTF-16の単一のコード単位で文字をエンコードできますか? 答えはイエスです。 UTF-16は16ビットの可変長符号化方式である。 それは、単一のコード単位で21⁶文字をエンコードできることを意味しますか?答えはいいえです。

答えはいいえです。

理論上は、このエンコード21⁶の文字コードポイント0000₁₆(0₁₀)FFFF₁₆(65535₁₀)がコードポイントとD800₁₆とDFFF₁₆を示すものではありません任意の文字としての無断転載を禁じます。したがって、0000₁₆からd7FF₁₆、E000₁₆からFfff₁₆までの文字をエンコードすることは安全です。 これは、UTF-16の1つのコード単位でエンコードできる文字のためのものです。

UTF-16の2つのコード単位でエンコードできるよりも、文字に関しては合計20ビットがあるため、22⁰以上の文字、つまり1,048,576文字をエンコードできます。したがって、合計で1,048,576+63,488をエンコードすることができ、これは1,112,064文字(1million文字以上)になります。 これはUTF文字セットの制限です。 UTF-16はこれらの多くの文字をエンコードすることができるので、他のUTFエンコーディングはこれらを超えた文字を表すことはできません。

UTF charset Code Points

コードポイントは文字に割り当てられたdecimal値であることがわかっているので、(Unicode)実際の文字に無効なコードポイントを割り当てては これまでのところ、無効なコードポイントは代理コードポイントです。1つのUTF-16コードユニットだけで、0000₁₆からd7FFFF、E000₁₆からFfff₁₆までの63,488文字をエンコードできます。 最後のコードポイントは65,535です。 これらはBMP文字と呼ばれます(後述)。

UTF-16の二つのコード単位では、1,048,576文字をエンコードすることができます。 これらはBMP文字の後に来るので、0値(コードポイント)から再び開始することはできないので、65,536でオフセットする必要があります。 これらの文字は補助文字(後述)と呼ばれます。したがって、最初の補助文字のコードポイント値は65536₁₀で、これは10000₁₆に相当します。 1,048,576文字をUTF-16の二つのコード単位でエンコードできるので、最後のコードポイントは1114111₁₀であり、これは10FFFFF₁₆に相当します。

それでは、単純な表形式で物事を分解してみましょう。この知識を使って、UTF-16でいくつかの文字をエンコードする方法を見てみましょう。 単純なASCII文字A(コードポイント:41º)、ヒンディー語(インド)言語の文字(aa、コードポイント:906ºと発音)、顔文字(happy face、コードポイント:1F60A ºと呼ばれる)を選びましょう。上の表からわかるように、Aとआの値はFFFF₁₆未満であるため、UTF-16のコード単位は1つだけでエンコードできます。

1つのコード単位で文字をエンコードする必要がある場合は、文字のコードポイントを16ビットの2進数に変換するだけです。 文字Aの場合、00000000 01000001₂はUTF-16表現です。同様に、文字आの場合、コードポイント906₁₆を16ビットの2進数00001001 00000110₂に変換するだけです。

通常、文字のコード単位を十六進数で表します。 したがって、文字Aの場合、UTF-16表現は0041₁₆であり、同様に、文字の場合、UTF-16表現आは0906₁₆です。

文字😊の場合、物事は少し異なります。 そのコードポイントは1F60A∞です。 上記のUTF-16テーブルを見ると、UTF-16の2つのコード単位でエンコードする必要があります。 それでは、どのように我々は始めるのですか?最初に、コードポイントから10000₁₆を減算する必要があります。

最初に、コードポイントから10000₁₆を減算する必要があります。 その理由は、UTF-16の2つのコード単位でエンコードされたすべての文字は、最後のコードポイントがFFFF₁₆であるBMP文字の後に来ているからです。

したがって、エンコードに使用されるビットの実際の値(2つのコード単位で20)を取得するには、コードポイントから10000₁₆を減算し、最終的な数値を使用して💡理解を深めるために、UTF-16の2つのコード単位で表される最初の文字は、すべての20ビットが0に設定されます。 したがって、この文字のコードポイントをエンコードするために使用されるビットの値は0です。 しかし、それでも、そのコードポイントはunicode文字セットによると10000₁₆です。 これは、これらの20ビットによって得られる値が10000₁₆に加算されて最終的なコードポイントが生成されるためです。p>

前に見たように、これらの2つのコード単位は以下のようになります。これらの20ビット(x)を文字コードポイントから受け取った値で埋めるだけです。 文字😊のコードポイントは1F60A₁₆です。 しかし、最初に、それから10000₁₆を引く必要があります。 私たちはF60A†を取得します。ここで、F60A₁₆を20ビットの2進数に変換し、上記のコード単位テンプレートの20ビットを埋める必要があります。 バイナリのF60A₁₆は0000111101 1000001010.です。 これで、これらの20個のプレースホルダのビットを埋めることができます。以下は最終的なコード単位です。

これらのコード単位が有効かどうか、実際にこれらのサロゲートペアがエンコードされた文字を表すことができるかどうかを確認する簡単な方法は、ブラウDiv>

(Chrome開発者ツール)

このオンラインツールを使用してutf-16コードポイントを生成することもできます。

Unicode Character Planes

平面は、21ºまたは65,536個のコードポイントの連続したグループです。 UTF-16ではコードポイントが最大10FFFFF₁₆に制限されているため、unicode標準では0から16までの合計17文字が使用されています。

21⁶文字はUTF-16の単一コード単位(サロゲートコードポイントを含む)で定義できるため、最初の(0番目の)平面を形成します。 この平面には、世界中の基本言語のほぼすべての文字が含まれています。 これが、この平面が基本多言語平面またはBMPと呼ばれる理由です。次に、UTF-16の2つのコード単位で定義されたコードポイントがあります。 コードポイント値をエンコードするために20ビットを持っているので、これらには22⁰文字が含まれています。 これらは16面(2≤x21≤)に分割されています。 これらは補助面と呼ばれます。

💡これらの平面の詳細については、このWikipediaの文書を読んでください。P>

UCS-2との比較

UCS-2は16ビット固定幅エンコーディングです。 つまり、コードポイントを表すために使用されるのは1つの16ビットコード単位だけです。 理論的には、UCS-2は21の異なる文字を表すことができますが、ねじれがあります。

💡ところで、この固定幅エンコーディングでは、UTF-16の関係を理解するために用語コード単位を使用しています。 実際には、符号化で固定されたコード単位のようなものはありません。P>

UCSはUnicode文字セットに従っているため、UCS-2の文字のエンコーディングは、一つのコード単位で表されるUTF-16の文字のエンコーディングと同じです。P>

💡UCSはUnicode文字セットに従っているため、サロゲート用に予約されたコードポイントで有効な文字をエンコードすることはできません。簡単に言えば、UCS-2には基本多言語面の文字が含まれています。 これは、いくつかの古い文書、およびソフトウェアは、UCS-2エンコーディングを使用した理由です。 しかし、UCS-2エンコーディングは廃止され、UTF-16が推奨されます。

エンディアンとBOM

前に説明したように、低レベルのUTFエンコードされた文書には、コード単位のシーケンスが含まれています。 UTF-8の場合、コード単位は8ビット長ですが、UTF-16の場合は16ビット長です。 これらのコード単位は文字を構成します。

UTF-8またはUTF-16デコーダは、文字を生成するために、一度に一つのコード単位を順番にコード単位を読み取ります。

各コード単位は、UTF-8またはUTF-16デコーダが見て、文字を表すのに十分であるかどうかを決定することができる数値を表し、または考慮すべき他のコード単位UTF-8に関しては、物事は簡単です。 各コード単位は8ビットの長さであるため、その8ビットの2進数を数値に変換するのは迅速かつ簡単です。 しかし、これはUTF-16の場合ではありません。UTF-16コード単位は、コードポイント値を表す16ビット(2バイト)の2進数です。

UTF-16コード単位は、コードポイント値を表す16ビット(2バイト)の2進数です。

複数のバイトから数値を生成するには、一般に、トリッキーであり、異なるシステムの動作が異なります。

この動作は、システムのエンディアンに依存します。 エンディアンについての以前の議論から、UTF-16コード単位値を記述する方法は二つあります。 ビッグエンディアン形式またはリトルエンディアン形式のいずれかです。

ビッグエンディアン形式では、MSBが最初に格納され、LSBが最後に格納されます。 これまでのところ、UTF-16コード単位の値をビッグエンディアン形式で記述しています。 UTF-16コード単位の値をリトルエンディアンで記述するには、バイトを交換する必要があります。

文字आについて話しましょう。 前の例から、UTF-16の1つのコード単位で表すことができ、16進表現でのエンコードは0906₁₆のようになります。

0906₁₆は16ビットの数値で、09はmsb、06はlsbです。 したがって、ビッグエンディアンアーキテクチャでは、09 06として格納されます。 ただし、リトルエンディアンアーキテクチャでは、06 09として格納されます。

したがって、システムがUTF-16文書を正しく読み取ることができるように、システムのエンディアンを念頭に置いて文字をエンコードするのは私たしかし、ユーザーのマシンがエンコードされた文書と互換性があるかどうかを事前にどのように伝えることができますか?

そして、システムのエンディアンは文書がどのようにデコードされるかに影響を与える可能性があるので、どのように公開して共有するのですか?

ここでBOMが登場します。

ここでBOMが登場します。 バイト順序マーク(BOM)は、テキストファイルまたはテキストデータの先頭に追加されるバイトシーケンスです。Unicodeでは、utf-16およびutf-32エンコーディングのbomとして機能するコードポイントFEFF₁₆を持つ文字を推奨しています。 この文字は、文書の最初の文字の前にする必要があります。 ただし、この文字は出力内のデコーダによって考慮されません。この文字(U+FEFF)はゼロ幅の非改行スペース(ZWNBSP)文字であり、不可視です。 したがって、デコーダがBOMを認識できなくても、表示される出力は生成されません。この文字はUTF-16の単一のコード単位で表され、16進表現ではFE(MSB)およびFF(LSB)のように見えます。

したがって、文字がビッグエンディアン形式でエンコードされている場合は、ファイルの先頭にFEFFをBOMとして追加する必要があり、文字がリトルエンディアン形式でエンコードされている場合は、ファイルの先頭にFFFE(reverse)をBOMとして追加する必要があります。Unicodeでは、UTF-16でエンコードされた文書にBOMを追加することを推奨しています。 ただし、BOMが欠落している場合は、ビッグエンディアン形式が想定されます。IANAは、UTF-16でエンコードされたドキュメントを示す識別子としてUTF-16を優先します。 ただし、ビッグエンディアン形式でエンコードされた文書にはUTF-16BEが使用され、リトルエンディアン形式にはUTF-16LEが使用されます。UTF-16BEまたはUTF-16LE名を使用する場合、BOMをファイルの前に追加することは推奨されません。 この場合でも、BOMが追加された場合、それはZWNBSP文字とみなされ、無視されません。💡UTF-16、UTF-16BE、およびUTF-16LEの名前は大文字と小文字を区別しません。UTF-16は2つのコード単位しか持たず、ほとんどの使用される文字はBMPセットに含まれるため、1つのコード単位で表現できます。

長所と短所

UTF-16は効率的です。 しかし、それは多くの問題が付属しています。UTF-16の最大の欠点は、ASCII互換ではないことです。 ASCII文字は単一のコード単位(16ビットの数値)でエンコードされるため、ASCIIデコーダでは正しくデコードできません。

UTF-16はASCII文字に不要なスペースを消費します。 ASCII文字のみを含むUTF-8エンコードされた文書と比較して、UTF-16でエンコードされた同じ文書のサイズは二倍大きくなります。UTF-16もシステムのエンディアンの影響を受けます。 BOMが欠落していて、適切なエンコード識別子(UTF-16LEなど)が使用されていない場合、UTF-16エンコードされたドキュメントが適切にデコードされないことがあり

UTF-16エンコーディングの性質上、有効な文字を表すことができないサロゲートコードポイントが導入されています。 また、Unicode文字セットは10FFFFF₁₆(最後のコードポイント)に制限されています。

これらの事実にもかかわらず、JavaScript、Javaなどのプログラミング言語のいくつかは、これらの事実にもかかわらず、

そして、WindowsのようなシステムはUTF-16エンコーディングを好む。

コメントを残す

メールアドレスが公開されることはありません。