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


395

Unicodeの基礎とは何か、なぜUTF-8またはUTF-16が必要なのか?私はこれをグーグルで研究し、ここでも検索しましたが、私にはわかりません。

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

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


123
あなたは絶対にすべてのソフトウェア開発者の絶対最小値を読む必要があるように聞こえますが、積極的にUnicodeと文字セットについて知っておく必要があります!それは何が起こっているのかについての非常に良い説明です。
Brian Agnew 2010

5
公式のUnicode WebサイトからのこのFAQにはいくつかの答えがあります。
Nemanja Trifunovic 2010

4
@John:非常に優れた紹介ですが、最終的な情報源ではありません。詳細のかなりの部分をスキップします(概要/紹介としてはこれで十分です)
Joachim Sauer

5
記事は素晴らしいですが、いくつかの間違いがあり、やや保守的な見方でUTF-8を表しています。補足としてutf8everywhere.orgを読むことをお勧めします。
Pavel Radzivilovsky、2012年

2
次のWebサイトをご覧ください。utf8everywhere.org– Vertexwahn 16
1

回答:


550

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

(それほどではないが)初期には、存在するのはASCIIだけでした。これは問題ではありませんでした。必要なのは、この文にあるようないくつかの制御文字、句読点、数字、および文字だけでした。残念ながら、今日の世界的な相互通信とソーシャルメディアの奇妙な世界は予見されておらず、英語、العربية、汉语、עִבְרִית、ε、λληνικά、およびភាសាខ្មែរを同じドキュメントに表示することも珍しくありません(私は古いものを壊していないといいのですが)ブラウザ)。

しかし、議論のために、ジョー・アベレージはソフトウェア開発者だとしましょう。彼は英語しか必要ないので、ASCIIだけを使いたいと主張しています。これはユーザーのジョーにとっては問題ないかもしれませんが、ソフトウェア開発者のジョーにとっては問題ではありません。世界の約半分が非ラテン文字を使用しており、ASCIIを使用することは間違いなくこれらの人々に無関心であり、さらにその上、彼はソフトウェアを大規模で成長している経済に締めくくっています。

したがって、すべての言語を含む包括的な文字セットが必要です。したがって、Unicodeが登場しました。すべての文字にコードポイントと呼ばれる一意の番号を割り当てます。他の可能なセットに対するUnicodeの利点の1つは、最初の256個のコードポイントがISO-8859-1と同一であるため、ASCIIであることです。さらに、一般的に使用される文字の大部分は、Basic Multilingual Plane(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分の1のメモリ効率で済みます。大きなWebページや長いWord文書など、大量のテキストを処理する場合、これはパフォーマンスに影響を与える可能性があります。

エンコードの基本

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

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

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

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

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

推奨/デフォルト/主要なエンコーディング:使用するUTFを選択する場合、通常は作業している環境の推奨標準に従うことが最適です。たとえば、WebではUTF-8が主要であり、HTML5以降はされている推奨のエンコーディング。逆に、.NETとJavaの両方の環境は、UTF-16文字タイプに基づいています。混乱して(そして誤って)、「Unicodeエンコーディング」への参照がよく行われます。これは通常、特定の環境での主要なUTFエンコーディングを指します。

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

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

同等性の比較: A、А、およびΑは同じように見えますが、それぞれラテン語、キリル語、ギリシャ語です。Cやlikeのようなケースもあります。1つは文字で、もう1つはローマ数字です。さらに、考慮すべき結合文字もあります。詳細については、Unicodeでの重複文字を参照してください。

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

その他?:


11
優れた答え、賞金の大きなチャンス;-)個人的には、UTF-8がユニバーサル文字エンコーディングあると主張する人もいますが、それは必ずしも全員が共有しているわけではないという意見です。
Joachim Sauer、

3
この段階ではまだ技術的すぎます。コンピュータにhelloという単語をUTF-8およびUTF-16で格納するにはどうすればよいですか。
FirstName LastName 2013年

1
たとえば、BMPがUTF-8で3バイトを使用する理由をさらに詳しく説明してもらえますか?その最大値は0xFFFF(16ビット)なので、アクセスに2バイトしかかからないと思いました。
マーク

2
@mark一部のビットはエンコード用に予約されています。UTF-8で2バイトを使用するコードポイントの場合、5つの予約済みビットがあり、コードポイントを選択するための11ビットのみが残ります。U + 07FFは、2バイトで表現できる最高のコードポイントになります。
DPenner1 2014年

1
ところで、ASCIIは128ビットのコードポイントのみを定義し、7ビットのみを使用して表現します。ISO-8859-1 / ISO-8859-15は、256のコードポイントを定義し、8ビットを使用して表現します。これら3つすべての最初の128コードポイントは同じです。
Tuxdude 2016

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

1
短く正確
Aritra Chatterjee

30

Unicodeはかなり複雑な標準です。恐れる必要はありませんが、仕事に備えましょう。[2]

信頼できるリソースは常に必要ですが、公式レポートは膨大であるため、以下を読むことをお勧めします。

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

簡単な説明:

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

主な違いは、ASCII文字はバイト(8ビット)に適合しますが、ほとんどのUnicode文字は適合しないことです。したがって、エンコーディングフォーム/スキーム(UTF-8やUTF-16など)が使用され、文字モデルは次のようになります。

すべての文字は、コードポイントと呼ばれる0から1,114,111(16進数:0-10FFFF)までの列挙された位置を保持します。エンコード形式は、コード単位配列にコードポイントをマッピングします。コード単位は、あなたは文字がメモリ、8ビット単位、16ビット単位で編成され、その上になりたい方法です。UTF-8は1〜4ユニットの8ビットを使用し、UTF-16は1または2ユニットの16ビットを使用して、最大21ビットのUnicode全体をカバーします。ユニットは接頭辞を使用して文字の境界を見つけることができます。ユニットが多いほど、ビットを占有する接頭辞が多くなります。したがって、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進数はバイトを表します。
また、Wikipediaの平面マップを見て、文字セットレイアウトの感触をつかんでください。


19

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

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

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


3
Microsoft がまだ UTF-16をUnicodeと呼んでいることに注意してください。2つは同じではありません
Mark Ransom 2017年

15

この記事はすべての詳細を説明します 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.

ここに画像の説明を入力してください


11

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

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

特定のエンコーディングの選択は、要件によって異なります。エンコーディングによってメモリ要件は異なります。処理する文字に応じて、バイトのシーケンスが最も少ないエンコーディングを選択して、それらの文字をエンコードする必要があります。

Unicode、UTF-8、UTF-16の詳細については、この記事をチェックしてください。

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


9

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


3
utf-8 3バイトシーケンスでデコードされた€(ユーロ)記号の例:E2 = 11100010 82 = 10000010 AC = 10101100ご覧のとおり、E2は1110で始まっているため、これは3バイトシーケンスです、82、ACは10で始まるため、これらは次のバイトです。ここで、「ペイロードビット」を連結します。
ブライトー2014年

5

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

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

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

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

簡単に言えば、作業中の言語またはプラットフォームですでにUTF-16が採用されていない限り、UTF-16は必要ありません。

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


「言語またはプラットフォームですでに採用されていない限り、UTF-16は必要ありません」:これは良い点ですが、ここには包括的なリストがあります:JavaScript、Java、.NET、SQL NCHAR、SQL NVARCHAR 、VB4、VB5、VB6、VBA、VBScript、NTFS、Windows API…。
トムブロジェット2018

2

UTFは、Unicode Transformation Formatの略です。基本的に、今日の世界では、他の何百もの言語で記述されたスクリプトがあり、以前に使用された基本的なASCIIではカバーされていません。したがって、UTFが誕生しました。

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.