146

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();
4

5 に答える 5

295

これについては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にはBOM(バイト順序マーク)があり、テキストがUTF-8でエンコードされていることを通知し、テキストにASCII文字しか含まれていない場合でもASCIIソフトウェアとの互換性を損なうことがあります。 。Microsoftソフトウェア(メモ帳など)は、UTF-8にBOMを追加するのが特に好きです。

UTF-16の主な長所:

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

主なUTF-16の短所:

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

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

于 2011-01-11T07:50:03.140 に答える
20

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

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

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

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

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

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

于 2011-01-11T07:41:19.987 に答える
8

セキュリティ:UTF-8のみを使用してください

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

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

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

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

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

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

于 2019-05-29T23:22:28.147 に答える
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;
    }
于 2011-01-11T19:29:46.337 に答える
-3

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

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

UTF-8は、文字に指定されたすべてのUnicode番号を1バイト(ASCIIの場合)、2 2バイト、4バイトなどで表現しようとします。

UTF-16は、最初に2バイトの文字に与えられたすべてのUnicode番号を表現しようとします。2バイトでは不十分な場合は、4バイトを使用します。それでも不十分な場合は、6バイトを使用します。

理論的には、UTF-16の方がスペース効率が高くなりますが、実際には、処理する文字のほとんど(データの98%)がASCIIであり、UTF-8はそれらを1バイトとUTF-16で表現しようとするため、UTF-8の方がスペース効率が高くなります。それらを2バイトで表現してみてください。

また、UTF-8はASCIIエンコーディングのスーパーセットです。したがって、ASCIIデータを期待するすべてのアプリはUTF-8プロセッサでも受け入れられます。これはUTF-16には当てはまりません。UTF-16はASCIIを理解できませんでした。これは、UTF-16を採用する上での大きなハードルです。

もう1つの注意点は、現時点ですべてのUNICODEが最大4バイトのUTF-8に収まる可能性があることです(世界のすべての言語を考慮)。これはUTF-16と同じであり、UTF-8(https://stackoverflow.com/a/8505038/3343801)と比較して実際にスペースを節約することはできません。

したがって、人々は可能な限りUTF-8を使用します。

于 2016-03-27T04:59:46.390 に答える