UTF-8とUTF-16の違いは?


137

UTF-8とUTF-16の違いは?なぜこれらが必要なのですか?

MessageDigest md = MessageDigest.getInstance("SHA-256");
String text = "This is some text";

md.update(text.getBytes("UTF-8")); // Change this to "UTF-16" if needed
byte[] digest = md.digest();

回答:


284

これについてはWebの周りに良い記事がたくさんあると思いますが、ここでは短い要約を示します。

UTF-8とUTF-16はどちらも可変長エンコーディングです。ただし、UTF-8では、文字が最低8ビットを占める可能性がありますが、UTF-16では、文字の長さは16ビットで始まります。

主なUTF-8プロ:

  • 数字、アクセントのないラテン文字などの基本的なASCII文字は、US-ASCII表現と同じ1バイトを占めます。このようにして、すべてのUS-ASCII文字列が有効なUTF-8となり、多くの場合、後方互換性が適切になります。
  • nullバイトがないため、nullで終了する文字列を使用できます。これにより、下位互換性も大幅に向上します。
  • UTF-8はバイトオーダーに依存しないため、ビッグエンディアン/リトルエンディアンの問題を心配する必要はありません。

UTF-8の主な短所:

  • 多くの一般的な文字は長さが異なるため、コードポイントによるインデックス作成とコードポイント数の計算が大幅に遅くなります。
  • バイトオーダーは重要ではありませんが、UTF-8には、テキストがUTF-8でエンコードされていることを通知するBOM(バイトオーダーマーク)が含まれている場合があり、テキストにASCII文字のみが含まれている場合でもASCIIソフトウェアとの互換性が失われます。Microsoftソフトウェア(メモ帳など)は、BOMをUTF-8に追加することを特に好みます。

主なUTF-16プロ:

  • ラテン語、キリル文字、ほとんどの中国語(PRCはBMP外の一部のコードポイントのサポートを必須にした)を含むBMP(基本的な多言語プレーン)文字、ほとんどの日本語は2バイトで表すことができます。これにより、テキストに補助文字が含まれていない場合のインデックス作成とコードポイント数の計算が高速化されます。
  • テキストに補助文字が含まれている場合でも、それらは16ビット値のペアで表されます。つまり、全長は2で割り切れるので、16ビットcharを文字列のプリミティブコンポーネントとして使用できます。

主なUTF-16の短所:

  • US-ASCII文字列の多くのnullバイト。これは、nullで終了する文字列がなく、大量のメモリが浪費されることを意味します。
  • これを固定長エンコーディングとして使用すると、多くの一般的なシナリオ(特に、米国/ EU /キリル文字のある国/イスラエル/アラブ諸国/イランなど)で「ほとんど機能する」ため、サポートされていない場所でサポートが機能しなくなることがよくあります。つまり、プログラマーはサロゲートペアを認識し、重要な場合には適切に処理する必要があります。
  • これは可変長であるため、コードポイントのカウントまたはインデックス作成にはコストがかかりますが、UTF-8よりは劣ります。

一般に、BE / LEは無関係であり(ネイティブの順序を使用するだけ)、インデックス化が高速であるため(サロゲートペアを適切に処理することを忘れないでください)、メモリ内の表現には通常UTF-16が適しています。一方、UTF-8はテキストファイルやネットワークプロトコルに非常に適しています。これは、BE / LEの問題がなく、Null終端が便利で、ASCII互換であるためです。


3
UTF16のBE / LE部分だけが欠落している:) UTF-8にはもう1つの欠点があります
。UTF16

4
はい、BE / LEを忘れました。ただし、特にメモリ内で使用する場合は、それほど大きな問題ではありません。UTF-8は、3バイト文字が含まれている場合にのみより長い出力を生成しますが、これは主に中国語と日本語を意味します。一方、テキストに多くのUS-ASCII文字が含まれている場合、生成される出力が短くなる可能性があるため、それが欠点かどうかは特定の状況に依存します。
Sergei Tachenov

私はutf-8の直近のプロ、より短い長さについて言及することすら考えていませんでした。utf-8のより長い出力については、それが理由で「可能性があります」が、ターゲットが極東の場合、デフォルトのエンコーディングはutf-16である必要があります。例と同様にmd.update(text.getBytes( "UTF-8")); ハッシュは双方向で安定しているため、エンコーディングは重要ではありません。
bestss

文字列をバイト配列に変換する最速の方法は、サンプルとして投稿されたそのようなものです
bestsss

UTF-8では文字の長さが異なるため、インデックス作成と長さの計算が遅くなりますが、UTF-16で文字の長さが異なることについては疑問です。
nicky_zs 2014

19

これらは、Unicode文字を表すための単純に異なるスキームです。

どちらも可変長です-UTF-16は、一般的に使用されているほとんどの文字を含む基本多言語プレーン(BMP)のすべての文字に2バイトを使用します。

UTF-8は、BMPの文字に1〜3バイトを使用し、U + 0000〜U + 1FFFFFの現在のUnicode範囲の文字に最大4バイトを使用します。必要に応じて、U + 7FFFFFFFまで拡張できます...ただし、すべてのASCII文字はそれぞれ1バイトで表されます。

メッセージダイジェストの目的では、ダイジェストを再作成しようとするすべての人が同じオプションを使用する限り、どれを選択してもかまいません。

UTF-8とUnicodeの詳細については、このページを参照してください

(すべてのJava文字はBMP内のUTF-16コードポイントであることに注意してください。U+ FFFFより上の文字を表すには、Javaでサロゲートペアを使用する必要があります。)


5

セキュリティ:UTF-8のみを使用

UTF-8とUTF-16の違いは?なぜこれらが必要なのですか?

UTF-16の実装にセキュリティ上の脆弱性が少なくともいくつかあります。詳細については、ウィキペディアを参照してください

WHATWGW3Cは、Web ではUTF-8のみを使用することを宣言しています。

ここで概説されている[セキュリティ]の問題は、UTF-8を排他的に使用することで解消されます。これは、多くの理由の1つであり、現在、すべてのものに必須のエンコーディングとなっています。

他のグループも同じことを言っています。

したがって、UTF-16はJavaやWindowsなどの一部のシステムで内部的に使用され続ける可能性がありますが、データファイルやデータ交換などでこれまでに見られなかったUTF-16の使用はほとんどなくなります。


4

これはUTF-8 / 16とは関係ありません(ただし、UTF16に変換され、BE / LE部分は1行で設定できます)が、以下はStringをbyte []に​​変換する最も速い方法です。たとえば、提供されたケースにぴったりです(ハッシュコード)。String.getBytes(enc)は比較的低速です。

static byte[] toBytes(String s){
        byte[] b=new byte[s.length()*2];
        ByteBuffer.wrap(b).asCharBuffer().put(s);
        return b;
    }

-2

UTF-8とUTF-16を区別する簡単な方法は、それらの間の共通点を識別することです。

特定の文字に対して同じUnicode番号を共有する以外は、それぞれが独自の形式です。

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