Unicodeエンコーディングの比較

この記事では、8ビットクリーンな環境と、上位ビットがセットされたバイト値の使用を禁止する環境の2種類の環境におけるUnicodeエンコーディングを比較します。当初、このような禁止事項は7データビットのみを使用するリンクを許可していましたが、一部の標準では残っているため、標準に準拠するソフトウェアの中には、これらの制限に準拠したメッセージを生成する必要があるものがあります。[詳細な説明が必要] Unicodeの標準圧縮スキームUnicodeのバイナリ順序圧縮は、サイズを単純に定量化することが難しいため、比較表から除外されています。

互換性の問題

ASCII文字のみを含むUTF-8ファイルは、ASCIIファイルと同一です。レガシープログラムは、非ASCII文字が含まれていても、一般的にUTF-8でエンコードされたファイルを処理できます。たとえば、Cのprintf関数は、フォーマット文字列を定義するためにASCIIの「%」文字のみを探すため、UTF-8文字列を出力できます。その他のバイトはすべて変更されずに出力されます

UTF-16UTF-32はASCIIファイルと互換性がないため、たとえファイルにASCIIサブセットの文字のみが含まれていることが分かっている場合でも、Unicode対応プログラムで表示、印刷、操作する必要があります。これらのファイルには多くのゼロバイトが含まれているため、これらのファイルを表す文字列は、一般的なヌル終端文字列処理ロジックでは操作できません。[a]このロジックを使用した文字列処理が普及しているため、WindowsJavaなどのUTF-16システムのコンテキストであっても、UTF-16テキストファイルは一般的に使用されていません。むしろ、ASCIIやISO-8859-1などの古い8ビットエンコーディングが依然として使用されており、Unicodeのサポートは完全に放棄されているか、Unicodeの代わりにUTF-8が使用されています。[要出典]まれな反例として、Mac OS X 10.3 Pantherで導入された「strings」ファイルがあります。これは、アプリケーションがメッセージの国際化バージョンを検索するために使用されますデフォルトでは、このファイルはUTF-16でエンコードされており、「UTF-8でエンコードされたファイルは動作が保証されません。」[1]

XML慣例的にUTF-8でエンコードされており[要出典]、すべてのXMLプロセッサは少なくともUTF-8とUTF-16をサポートする必要があります。[2]

効率性

UTF-8ではUnicode文字をエンコードするために8、16、24、または32ビット(1~4バイト)が必要です。UTF -16では文字をエンコードするために16ビットまたは32ビットが必要です。UTF -32では文字をエンコードするために常に32ビットが必要です

最初の 128 個の Unicodeコード ポイント(U+0000 から U+007F) は、C0 制御文字および基本ラテン文字に使用され、ASCII に対応しており、UTF-8 では 8 ビット、UTF-16 では 16 ビット、UTF-32 では 32 ビットを使用してエンコードされます。次の 1,920 文字 (U+0080 から U+07FF) は、ほぼすべてのラテン文字アルファベットのほか、ギリシャ語キリル文字コプト語、アルメニア語、ヘブライ語アラビアシリア語ターナ文字およびN'Koで使用される残りの文字を表します。この範囲の文字をエンコードするには、UTF-8 と UTF-16 の両方で 16 ビット、UTF-32 では 32 ビットが必要です。基本多言語面の残りの文字であり、世界のほとんどの現存言語の残りの文字を表すことができる U+0800 から U+FFFF の場合、文字をエンコードするには UTF-8 では 24 ビット、UTF-16 では 16 ビット、UTF-32 では 32 ビットが必要です。補助面の文字を表すコード ポイント U+010000 から U+10FFFF では、UTF -8、UTF-16、UTF-32 で 32 ビットが必要です。

U+0800からU+FFFFの範囲のコードポイントよりもASCIIコードポイントの数が多い場合、UTF-8のファイルはUTF-16よりも短くなります。UTF-8を推奨する人々は、高域の文字のみを使用する言語で書かれた実際の文書は、スペース、数字、句読点、改行、HTMLまたはXMLマークアップ(docxファイルodtファイルなど)、ラテン文字で書かれた埋め込み単語や頭字語の多用により、UTF-8では依然として短いことが多いと主張しています。[3]対照的に、UTF-32は、U+10000未満のコードポイントがない限り、常に長くなります

UTF-EBCDICのすべての印刷可能文字は、UTF-8と少なくとも同じバイト数を使用し、C1制御コードを1バイトとしてエンコードできるようにしたため、ほとんどの文字はそれ以上のバイト数を使用します。7ビット環境では、UTF-7は、ほぼすべての種類のテキストにおいて、 quoted-printableまたはbase64と他のUnicodeエンコードの組み合わせよりもスペース効率に優れています[詳細な説明が必要](以下の「7ビット環境」を参照)。

処理時間

UTF-8やUTF-16などの可変長エンコーディングのテキストは、コードポイントを扱う場合よりも個々のコードユニットを扱う必要がある場合、処理が難しくなります。コードユニットのシーケンスの検索では区切りを気にしないため、文字のサイズが可変かどうかは検索に影響しません。ただし、エンコーディングが自己同期型である必要があります。UTF-8とUTF-16はどちらも自己同期型です。よくある誤解として、「 n番目の文字を見つける」必要があり、そのためには固定長エンコーディングが必要だというものがあります。しかし、実際の使用では、 nという数値はn−1文字を調べることからのみ導き出されるため、いずれにしても順次アクセスが必要です。[要出典]

処理上の問題

処理のためには、フォーマットは検索、切り捨てが容易で、一般的に安全に処理できる必要があります。[要出典]すべての通常のUnicodeエンコーディングは、何らかの固定サイズのコード単位を使用します。フォーマットとエンコードされるコードポイントに応じて、これらのコード単位の1つ以上がUnicodeコードポイントを表します。検索と切り捨てを容易にするために、シーケンスはより長いシーケンス内、または他の2つのシーケンスの境界を越えて出現してはなりません。UTF-8、UTF-16、UTF-32、UTF-EBCDICにはこれらの重要な特性がありますが、UTF-7GB 18030にはそれらがありません

固定サイズの文字は便利ですが、UTF-32のようにコードポイントあたりのバイト数が固定であっても、文字の結合により、表示文字あたりのバイト数は固定ではありません。これらの非互換性や異なるエンコード方式間のその他の癖を考慮すると、インターフェース全体で同じ(または互換性のある)プロトコルでUnicodeデータを処理すること(例:API/ライブラリの使用、クライアント/サーバーモデルでのUnicode文字の処理など)は、一般的にパイプライン全体を簡素化し、同時に潜在的なバグの原因を排除することができます。

UTF-16が普及しているのは、多くのAPIがUnicodeが16ビット固定幅(UCS-2と呼ばれる)だった時代に遡るためです。しかし、UTF-16を使用すると、基本多言語面外の文字が特別なケースになり、それらの処理に関連する見落としのリスクが高まります。とはいえ、サロゲートペアを誤って処理するプログラムはおそらくシーケンスの結合にも問題を抱えているため、UTF-32を使用しても、マルチコード単位文字の不適切な処理というより一般的な問題を解決できる可能性は低いでしょう

保存されているデータ(ファイルの内容や名前など)がUTF-8である場合、APIとしてUTF-16またはUTF-32を使用するシステムを作成することは非常に困難です。これは、UTF-8で使用されるバイト配列に物理的に無効なシーケンスが含まれる可能性があるという、見落とされがちな事実によるものです。たとえば、UTF-16 APIを使用して無効なUTF-8ファイル名を修正することは不可能です。UTF-16文字列をその無効なファイル名に変換できないためです。逆は当てはまりません。無効なUTF-16を一意の(技術的には無効ですが)UTF-8文字列に変換するのは簡単です。そのため、UTF-8 APIはUTF-8とUTF-16の両方のファイルと名前を制御できるため、このような混在環境ではUTF-8が優先されます。UTF-16システムで使用されている残念ですが、はるかに一般的な回避策は、UTF-8をCP-1252などの他のエンコーディングとして解釈し、非ASCIIデータの 文字化けを無視することです。

通信とストレージ用

UTF-16とUTF-32にはエンディアンが定義されていないため、バイト指向のネットワーク経由で受信する場合、またはバイト指向のストレージから読み取る場合は、バイトオーダーを選択する必要があります。これは、テキストの先頭にバイトオーダーマークを使用するか、ビッグエンディアン(RFC 2781)を想定することで実現できます。UTF -8UTF-16BEUTF-32BEUTF-16LE 、およびUTF-32LEは単一のバイトオーダーで標準化されており、この問題はありません

バイトストリームが破損した場合、一部のエンコーディングは他のエンコーディングよりも回復性に優れています。UTF-8とUTF-EBCDICは、次のコードポイントの開始時に破損または欠落したバイトの後、常に再同期できるため、この点で最も優れています。GB 18030は、次のASCII非数値まで回復できません。UTF-16は変更されたバイトを処理できますが、奇数バイトの欠落は処理できません。この場合、後続のテキスト全体が文字化けします(ただし、珍しい文字や未割り当ての文字が生成されます)。[b]ビットが失われる可能性がある場合、すべてのビットが後続のテキストを文字化けしますが、UTF-8は再同期できます。これは、不正なバイト境界により、数バイトを超えるほとんどすべてのテキストで無効なUTF-8が生成されるためです。

詳細

以下の表は、異なるUnicode範囲のコードポイントあたりのバイト数を示しています。必要な追加コメントは表に含まれています。これらの数値は、テキストブロックの開始と終了のオーバーヘッドが無視できると想定しています。

8ビット環境

コード範囲(16進数) UTF-8 UTF-16 UTF-32 UTF-EBCDIC GB 18030
000000 – 00007F 1 2 4 1 1
000080 – 00009F 2
GB 2312 / GBKから継承された文字(例:ほとんどの
漢字)の場合は2、
それ以外 は4
0000A0 – 0003FF 2
000400 – 0007FF 3
000800 – 003FFF 3
004000 – 00FFFF 4
010000 – 03FFFF 4 4 4
040000 – 10FFFF 5

7ビット環境

この表はすべての特殊なケースを網羅しているわけではないため、推定と比較のみに使用してください。エンコードにおけるテキストのサイズを正確に判断するには、実際の仕様を参照してください。

コード範囲(16進数) UTF-7 UTF-8 quoted
-printable
UTF-8 base64 UTF-16 q.-p UTF-16 base64 GB 18030 q.-p. GB 18030 base64
ASCII
グラフィック文字
(U+003D "=" を除く)
「直接文字」の場合は1(一部のコードポイントではエンコーダー設定に依存)、U+002B "+" の場合は2、それ以外の場合は000080~00FFFFと同じ 1 1+13 4 2+23 1 1+13
00003D(等号) 3 6 3
ASCII
制御文字
000000~00001F
および00007F
直接性に応じて1または3 直接性に応じて1または3
000080~0007FF シングルバイト文字の連続内の孤立したケースの場合は5。連続が2の場合+文字ごとに23と、整数バイトにするためのパディング、および連続の開始と終了のための2バイト 6 2+23 バイト値をエスケープする必要があるかどうかに応じて2~6 GB2312/GBKから継承された文字(例:ほとんどの中国語の文字)の場合は4~6
その他の場合は8
2+GB2312/GBKから継承された文字(例:
ほとんどの中国語の文字)の場合は2 3、5+その他すべての場合は 1 ⁄ 3
000800 – 00FFFF 9 4
010000 – 10FFFF 単独の場合は8、5+文字ごとに 13 、整数までのパディング、連続する場合は2 12 5+13 サロゲートの下位バイトをエスケープする必要があるかどうかに応じて8~12 5+13 8 5+13

エンディアンはサイズに影響しません(UTF-16BEUTF-32BEは、それぞれUTF-16LEUTF-32LEと同じサイズです)。quoted-printableでUTF-32を使用することは非常に非現実的ですが、実装すると、コードポイントごとに8~12バイト(平均で約10バイト)になります。つまり、BMPの場合、各コードポイントはquoted-printable/UTF-16の同じコードよりも正確に6バイト多く占めます。Base64/UTF-32では5+どのコードポイントでも1/3バイトなります。

quoted-printableまたはUTF-7でのASCII制御文字は、直接表現することも、エンコード(エスケープ)することもできます。特定の制御文字をエスケープする必要があるかどうかは多くの状況によって異なりますが、テキストデータ内の改行は通常、直接コード化されます

Compression schemes

BOCU-1SCSUは、Unicodeデータを圧縮する2つの方法です。これらのエンコードは、テキストの使用頻度に依存します。ほとんどのテキストランは同じ文字を使用します。たとえば、ラテン文字キリル文字ギリシャ文字などです。この通常の使用により、多くのテキストランをコードポイントあたり約1バイトまで圧縮できます。これらの状態のあるエンコードにより、文字列の任意の位置にあるテキストへのランダムアクセスが困難になります。

これらの2つの圧縮方式は、 zipbzip2などの他の圧縮方式ほど効率的ではありません。これらの汎用圧縮方式は、長いバイトランをわずか数バイトに圧縮できます。SCSUおよびBOCU -1圧縮方式は、UTF-8、UTF-16、またはUTF-32でエンコードされたテキストの理論上の25%を超えて圧縮することはありません。他の汎用圧縮方式は、元のテキストサイズの10%まで簡単に圧縮できます。汎用方式では、良好な圧縮率を得るために、より複雑なアルゴリズムとより長いテキストチャンクが必要です

Unicodeテクニカルノート#14には、圧縮方式のより詳細な比較が記載されています。

歴史:UTF-5とUTF-6

ドメイン名の国際化(IDN)のために、UTF-5とUTF-6の提案がなされてきました。UTF-5提案ではbase 32エンコーディングが使用されていましたが、Punycodeは(他の点では異なりますが)base 36エンコーディングです。5ビットのコード単位であるUTF-5という名前は、 2 5 = 32という式で説明されます。 [4] UTF-6提案では、UTF-5にランニングレングスエンコーディングが追加されました。ここで、6は単にUTF-5に1を加えたものを表します。[5] IETF IDN WG後に、この目的のために、より効率的なPunycodeを採用しました。 [ 6]

真剣に検討されていない

UTF-1は真剣に受け入れられることはありませんでした。UTF-8の方がはるかに頻繁に使用されています

ノネットエンコーディングUTF-9とUTF-18はエイプリルフールのRFCジョーク仕様ですが、UTF-9は機能するノネットUnicode変換形式であり、UTF-18はUnicode 12以下のすべての非私的使用コードポイントで機能するノネットエンコーディングです(ただし、補足私的使用領域またはUnicode 13以降の一部では機能しません) 。

注記

  1. ^ 文字列をヌル文字で終了しないASCIIソフトウェアは、 UTF-16およびUTF-32でエンコードされたファイルを正しく処理します(そのようなファイルは、ASCIIサブセット文字のみを含む場合、ヌル文字で埋め込まれた通常のASCIIとして表示されます)が、そのようなソフトウェアは一般的ではありません。 [要出典]
  2. ^ 対照的に、UTF-16では、偶数バイトの欠落によって最大1文字が文字化けします。

参考文献

  1. ^ 「Apple Developer Connection:国際化プログラミングトピック:文字列ファイル」
  2. ^ 「エンティティの文字エンコーディング」。拡張マークアップ言語(XML)1.0(第5版)ワールドワイドウェブコンソーシアム。2008年。
  3. ^ 「UTF-8 Everywhere」。utf8everywhere.org 2022年8月28日閲覧
  4. ^ Seng, James、「UTF-5、UnicodeとISO 10646の変換形式」、2000年1月28日
  5. ^ Welter, Mark; Spolarich, Brian W. (2000年11月16日). 「UTF-6 - IDのためのもう1つのASCII互換エンコーディング」. IETF Datatracker . 2016年5月23日時点のオリジナルからのアーカイブ2016年4月9日閲覧。
  6. ^ 「国際化ドメイン名 (idn)」. Internet Engineering Task Force . 2023年3月20日閲覧。
「https://en.wikipedia.org/w/index.php?title=Comparison_of_Unicode_encodings&oldid=1323107582#UTF-6」より取得