web-dev-qa-db-ja.com

Unicode、UTF-8、UTF-16とは何ですか?

Unicodeの基本は何ですか?また、なぜUTF-8またはUTF-16が必要なのですか?私はこれをGoogleで調べ、ここでも検索しましたが、それは私には明らかではありません。

VSSでは、ファイル比較を行うときに、2つのファイルのUTFが異なるというメッセージが表示されることがあります。これはなぜでしょうか。

簡単に説明してください。

343
SoftwareGeek

なぜUnicodeが必要なのですか?

(それほどではないが)初期の頃は、存在していたのはASCIIだけでした。これまでのところ必要だったのは、少数の制御文字、句読点、数字、およびこの文の中の数字のような文字だけだったので、これは問題ありませんでした。残念なことに、今日の世界的な相互通信とソーシャルメディアの奇妙な世界は予見されていませんでした、そして英語、英語、スウェーデン語、ελληνικά、およびភាសាខ昔を同じ文書で見ることも珍しくありません。ブラウザ)。

しかし議論のために、Joe Averageがソフトウェア開発者であるとしましょう。彼は彼がこれまでに英語だけを必要とし、そしてそれだけでASCIIを使いたいと主張するだろうと主張している。これはJoe theuserでは問題ないかもしれませんが、Joe thesoftware developerでは問題ありません。世界の約半数がラテン語以外の文字を使用しており、ASCIIを使用することはこれらの人々にはおそらく矛盾しています。それに加えて、彼は自分のソフトウェアを大きく成長する経済に締め付けています。

したがって、alllanguagesを含む包括的な文字セットが必要です。こうしてUnicodeが登場しました。すべての文字にコードポイントと呼ばれる固有の番号を割り当てます。他の可能なセットに対するUnicodeの利点の1つは、最初の256個のコードポイントが ISO-8859-1 と同一であり、したがってASCIIでもあることです。さらに、 基本多言語面(BMP)と呼ばれる領域では、一般的に使用される文字の大部分は2バイトしか表現できません この文字セットにアクセスするには文字エンコーディングが必要です。質問がするように、私はUTF-8とUTF-16に集中します。

メモリの考慮事項

では、これらのエンコーディングのどの文字に何バイトアクセスすればよいのでしょうか。

  • UTF-8:
    • 1バイト:標準ASCII
    • 2バイト:アラビア語、ヘブライ語、ほとんどのヨーロッパ言語のスクリプト(最も注目に値するのは グルジア語 を除く)
    • 3バイト:BMP
    • 4バイト:全Unicode文字
  • UTF-16:
    • 2バイト:BMP
    • 4バイト:全Unicode文字

BMPに含まれていない文字には、古代の文字、数学記号、音楽記号、およびめったにない 中国語/日本語/韓国語(CJK) 文字.

ほとんどの場合ASCII文字を扱う場合は、UTF-8の方が確かにメモリ効率がよくなります。ただし、ヨーロッパ以外のスクリプトを使用している場合は、UTF-8を使用すると、UTF-16より最大1.5倍メモリ効率が低下する可能性があります。大きなWebページや長いWord文書など、大量のテキストを扱う場合は、パフォーマンスに影響が出る可能性があります。

エンコーディングの基本

注:UTF-8とUTF-16がどのようにエンコードされているかがわかっている場合は、実用的なアプリケーションのために次のセクションに進んでください。

  • UTF-8:標準のASCII(0-127)文字の場合、UTF-8コードは同一です。既存のASCIIテキストとの後方互換性が必要な場合、これはUTF-8を理想的なものにします。他の文字は2〜4バイトが必要です。これは、それらがマルチバイト文字の一部であることを示すために、これらの各バイトにいくつかのビットを予約することによって行われます。特に、各バイトの最初のビットは、ASCII文字との衝突を避けるために1です。
  • UTF-16:有効なBMP文字の場合、UTF-16表現は単にそのコードポイントです。ただし、BMP以外の文字の場合、UTF-16ではサロゲートペアが導入されました。この場合、2つの2バイト部分の組み合わせが非BMP文字にマップされます。これらの2バイト部分はBMP数値範囲から来ていますが、BMP文字として無効であることがUnicode標準によって保証されています。また、UTF-16は基本単位が2バイトなので、 エンディアン の影響を受けます。補償するために、予約済みバイトオーダーマークをエンディアンを示すデータストリームの先頭に付けることができます。したがって、UTF-16入力を読んでいて、エンディアンが指定されていない場合は、これを確認する必要があります。

見てわかるように、UTF-8とUTF-16はお互いにほとんど互換性がありません。それで、もしあなたがI/Oをしているのなら、あなたが使っているエンコーディングを知っていることを確認してください!これらのエンコーディングの詳細については、 UTF FAQ を参照してください。

実用的なプログラミングの考慮事項

文字データ型と文字列データ型:プログラミング言語ではどのようにエンコードされていますか。それらが生のバイトであるならば、あなたが非ASCII文字を出力しようとした瞬間、あなたはいくつかの問題に遭遇するかもしれません。また、文字タイプがUTFに基づいている場合でも、文字列が正しいUTFであるとは限りません。それらは違法なバイト列を許すかもしれません。一般的に、C、C++、およびJavaでは ICU のように、UTFをサポートするライブラリを使用する必要があります。いずれにせよ、もしあなたがデフォルトエンコーディング以外の何かを入出力したいのなら、あなたはそれを最初に変換しなければならないでしょう。

推奨/デフォルト/支配的なエンコーディング:どのUTFを使用するかを選択するときは、通常、作業している環境の推奨標準に従うのが最善です。 8がWeb上で主流であり、HTML 5以降、これは 推奨エンコーディング となっています。逆に、.NET環境とJava環境はどちらもUTF-16文字型に基づいています。混乱を招くように(そして誤って)、「Unicodeエンコーディング」と呼ばれることがよくあります。これは、通常、特定の環境で優勢なUTFエンコーディングを指すものです。

ライブラリサポート:サポートしているライブラリはどのようなエンコーディングですか?彼らはコーナーケースを支持しますか?必要性は発明の母であるため、1、2、さらには3バイトの文字が頻繁に発生する可能性があるため、UTF-8ライブラリは通常4バイト文字を適切にサポートします。しかし、めったに発生しないため、すべてのUTF-16ライブラリがサロゲートペアを適切にサポートしているとは限りません。

文字数のカウント:Unicodeには結合文字があります。たとえば、コードポイントU + 006E(n)とU + 0303(結合チルダ)はñを形成しますが、コードポイントU + 00F1はñを形成します。これらは同一に見えるはずですが、単純なカウントアルゴリズムは最初の例では2を、後者の例では1を返します。これは必ずしも間違っているわけではありませんが、望ましい結果ではないかもしれません。

等しいかどうかを比較すると、A、A、Aは同じように見えますが、それぞれラテン、キリル、ギリシャです。 Cやandのような場合もあります。1つは文字、もう1つはローマ数字です。さらに、考慮すべき結合文字もあります。詳しくは、 Unicodeでの文字の重複 を参照してください。

サロゲートペア:これらはSOで十分な頻度で表示されるため、ここではいくつかのリンク例を示します。

その他?:

490
DPenner1
  • Unicode
    • 世界中で使用されている文字のセットです。
  • UTF-8
    • unicodeですべての可能な文字(コードポイントと呼ばれる)をエンコードできる文字エンコード。
    • コード単位は8ビット
    • unicodeをエンコードするために1から4のコード単位を使用する
    • 00100100は "$"(1つの8ビット);11000010 10100010は " )¢ "(2つの8ビット);11100010 10000010 10101100" "(3つの8ビット)
  • UTF-16
    • 別の文字エンコーディング
    • コード単位は16ビット
    • 1から2つのコード単位を使用してUnicodeをエンコードする
    • 00000000 00100100は "$"(1つの16ビット);11011000 01010010 11011111 01100010は "???? "(2つの16ビット)
57
wengeezhang

Unicodeはかなり複雑な規格です。あまり恐れないでください、しかしいくつかの仕事のために準備してください! [2]

信頼できるリソースが常に必要とされていますが、公式の報告書は膨大であるため、以下を読むことをお勧めします。

  1. 絶対最低限すべてのソフトウェア開発者は、絶対に、確実にUnicodeと文字セットについて知っておく必要があります(言い訳は不要です) Stack ExchangeのCEO、Joel Spolskyによる紹介。
  2. BMP以降へ! その後、副社長、テクニカルディレクターを務めるEric MullerによるThe Unicode Consortiumによるチュートリアル。 (最初の20枚のスライドが完成したら完了です)

簡単な説明

コンピュータはバイトを読み取り、人々は文字を読み取るので、文字をバイトにマッピングするにはエンコード標準を使用します。 ASCIIは最初に広く使用された規格ですが、ラテン語のみをカバーします(7ビット/文字は128の異なる文字を表すことができます)。 Unicodeは、世界中で使用可能なすべての文字をカバーすることを目標とした標準です(最大1,114,112文字、最大21ビット/文字まで)。現在のUnicode 8.0では、合計で120,737文字が指定されています。

主な違いは、ASCII文字は1バイト(8ビット)に収まることができますが、ほとんどのUnicode文字は収まらないことです。そのため、エンコード形式/スキーム(UTF-8やUTF-16など)が使用され、文字モデルは次のようになります。

すべての文字は、コードポイントと呼ばれる0から1,114,111(16進数:0-10FFFF)の列挙位置を保持します。
エンコード形式は、コードポイントをコード単位シーケンスにマップします。 コード単位は、文字をメモリ、8ビット単位、16ビット単位などで編成する方法です。最大21ビットのUnicode全体をカバーするために、UTF-8は1から4単位の8ビットを使用し、UTF-16は1または2単位の16ビットを使用します。単位は文字境界を見分けることができるように接頭辞を使用し、より多くの単位はビットを占めるより多くの接頭辞を意味します。そのため、UTF-8はラテン文字に1バイトを使用しますが、基本多言語面内のそれ以降の文字には3バイトが必要ですが、UTF-16はこれらすべてに2バイトを使用します。そしてそれが彼らの主な違いです。
最後に、エンコード方式(UTF-16BEまたはUTF-16LEのような)は、コード単位シーケンスをバイトシーケンスにマップ(直列化)します。

キャラクター:π
コードポイント:U + 03C0
符号化形式(コード単位):
UTF-8:CF 80
UTF-16:03C0
エンコーディングスキーム(バイト):
UTF-8:CF 80
UTF-16BE:03 C0
UTF-16LE:C0 03

ヒント:16進数は4ビットを表すので、2桁の16進数は1バイトを表します
また、ウィキペディアのPlane mapsを見て、文字セットのレイアウトを理解してください。

26
Neuron

もともと、Unicodeは固定幅の16ビットエンコーディング(UCS-2)を持つことを目的としていました。 JavaやWindows NTのようなUnicodeの初期の採用者たちは、16ビット文字列を中心にそれらのライブラリを構築しました。

後になって、Unicodeの範囲は歴史的な文字を含むように拡大されました、それは16ビットのエンコーディングがサポートする65,536以上のコードポイントを必要とします。 UCS-2を使用していたプラットフォームで追加の文字を表現できるようにするために、UTF-16エンコーディングが導入されました。補助面の文字を表すために「サロゲートペア」を使用します。

一方、古いソフトウェアやネットワークプロトコルの多くは8ビット文字列を使用していました。 UTF-8が作られたので、これらのシステムはワイド文字を使わなくてもUnicodeをサポートできます。 7ビットASCIIと下位互換性があります。

18
dan04

この記事では、すべての詳細について説明します http://kunststube.net/encoding/

バッファへの書き込み

4バイトのバッファに書き込む場合、シンボルをUTF8でエンコードすると、バイナリは次のようになります。

00000000 11100011 10000001 10000010

あなたが4バイトのバッファに書き込むならば、UTF16エンコーディングでシンボル、あなたのバイナリは以下のようになるでしょう:

00000000 00000000 00110000 01000010

あなたが見ることができるように、あなたがあなたのコンテンツでどの言語を使うかに応じて、これはそれに応じてあなたの記憶に影響を与えます。

例えばこの特定のシンボルの場合:次のシンボルに使用する2つの予備バイトがあるため、UTF16エンコーディングがより効率的です。しかし、それはあなたが日本のアルファベットのためにUTF16を使わなければならないという意味ではありません。

バッファからの読み込み

もしあなたが上記のバイトを読みたいのであれば、あなたはそれがどのエンコーディングで書かれているかを知っていて、それを正しくデコードし直さなければなりません。

例えばこれをデコードすると、00000000 11100011 10000001 10000010をUTF16エンコードに変換すると、ではなくになります。

注:エンコードとUnicodeは、2つの異なる点があります。 Unicodeは大きな (テーブル) で、各シンボルは一意のコードポイントにマッピングされます。例えば記号(文字)には (コードポイント)30 42(16進数)があります。一方、エンコードは、ハードウェアに格納するときに、シンボルをより適切な方法に変換するアルゴリズムです。

30 42 (hex) - > UTF8 encoding - > E3 81 82 (hex), which is above result in binary.

30 42 (hex) - > UTF16 encoding - > 30 42 (hex), which is above result in binary.

enter image description here

12
InGeek

なぜユニコード?なぜならASCIIは127文字しかないからです。 128から255までは国によって違います、それでコードページがあります。だから彼らは言ったことができます1114111文字まで持っています。それでは、どのようにして最高のコードポイントを保存しますか? 21ビットで保存する必要があるので、32ビットと11ビットが無駄になるDWORDを使用します。そのため、DWORDを使用してUnicode文字を格納する場合は、DWORDの値がコードポイントと正確に一致するため、これが最も簡単な方法です。しかしDWORD配列は、もちろんWord配列よりも大きく、もちろんBYTE配列よりも大きいです。だからこそ、utf-32だけでなくutf-16もあります。しかし、utf-16はWordストリームを意味し、Wordは16ビットであるため、最高のコードポイント1114111はどのようにWORDに収まるのでしょうか。できない!そこで彼らは65535以上のものすべてをサロゲートペアと呼ぶDWORDに入れました。このようなサロゲートペアは2つのWORDSであり、最初の6ビットを見れば検出できます。それでは、UTF-8はどうでしょうか。これはバイト配列またはバイトストリームですが、最高のコードポイント1114111を1バイトに収めるにはどうすればよいでしょうか。できない!わかりました、それで彼らはまたDWORDを入れますか?それともWordでしょ?ほぼ正しい!彼らはutf-8シーケンスを発明しました。つまり、127を超えるすべてのコードポイントは、2バイト、3バイト、または4バイトのシーケンスにエンコードされる必要があります。うわー!しかし、どうやってそのようなシーケンスを検出できるのでしょうか。 127までのすべてがASCIIで、1バイトです。 110から始まるのは2バイトのシーケンス、1110から始まるのは3バイトのシーケンス、そして11110から始まるのは4バイトのシーケンスです。これらのいわゆる「スタートバイト」の残りのビットはコードポイントに属します。今シーケンスに応じて、次のバイトが続く必要があります。次のバイトは10で始まり、残りのビットは6ビットのペイロードビットであり、コードポイントに属します。開始バイトとそれに続くバイトのペイロードビットを連結すると、コードポイントが得られます。それがすべてのUTF-8の魔法です。

9
brighty

Unicodeは、すべての言語の文字をコードポイントと呼ばれる特定の数値にマップする標準です。これを行う理由は、同じコードポイントのセットを使用してさまざまなエンコードを可能にできるためです。

UTF-8とUTF-16はそのような2つのエンコーディングです。それらはコードポイントを入力として受け取り、そして明確に定義された公式を使ってそれらをエンコードしてエンコードされた文字列を生成します。

特定のエンコーディングを選択することはあなたの要件に依存します。エンコーディングが異なれば、メモリ要件も異なります。処理する文字に応じて、これらの文字をエンコードするために最小のバイトシーケンスを使用するエンコードを選択してください。

Unicode、UTF-8、およびUTF-16の詳細については、こちらの記事を参照してください。

すべてのプログラマがUnicodeについて知っておくべきこと

8
Kishu Agarwal

ASCII - ソフトウェアは、与えられた文字に対してメモリ内の8ビットバイトのみを割り当てます。対応する10進値が10進値で128を下回るため、英語および採用された(ファサードのようなローンワード)文字に適しています。 Cプログラムの例.

UTF-8 - ソフトウェアは、指定された文字に1から4の可変8ビットバイトを割り当てます。ここで変数とはどういう意味ですか?ブラウザでHTMLページを介して文字「A」を送信しているとします(HTMLはUTF-8)。対応するAの10進値は65です。10進に変換すると01000010になります。これには1バイトしか必要ありません。 1ワードのメモリは、Wordのファサードの「ç」のような特別に採用された英語の文字にも割り当てられます。ただし、ヨーロッパ言語の文字を格納する場合は2バイトが必要なので、UTF-8が必要です。ただし、アジア文字を使用する場合は、最低2バイト、最高4バイトが必要です。同様に、絵文字は3から4バイトを必要とします。 UTF-8はあなたのすべてのニーズを解決します。

UTF-16は1文字あたり最小2バイト、最大4バイトを割り当てます。1または3バイトは割り当てません。各文字は16ビットまたは32ビットで表されます。

では、なぜUTF-16が存在するのでしょうか。もともと、Unicodeは8ビットではなく16ビットでした。 JavaはUTF-16のオリジナルバージョンを採用しました。

一言で言えば、あなたが取り組んでいる言語またはプラットフォームによってすでに採用されていない限り、どこにでもUTF-16は必要ありません。

Webブラウザによって起動されたJavaプログラムはUTF-16を使用しますが、WebブラウザはUTF-8を使用して文字を送信します。

4
Siva

UTFはUnicode Transformation Formatの略です。今日の世界では基本的に以前に使用された基本的なASCIIでカバーされていないフォーマットで他の何百もの言語で書かれたスクリプトがあります。それゆえ、UTFが登場しました。

UTF-8には文字エンコード機能があり、そのコード単位は8ビットですが、UTF-16の場合は16ビットです。

2
kg11