5

入力をUTF-8からISO-8859-1(Latin 1)にトランスコードする必要があるアプリケーションを作成しています。

一部のウムラウト文字のエンコードがおかしくなることがあることを除いて、すべて正常に機能します。たとえば、2ドット(0xEB)のラテン語1 Eは、通常UTF-8 0xC3 0xABとして提供されますが、0xC3 0x830xC20xABとして提供される場合もあります。

これはさまざまなソースから何度も発生し、最初と最後の文字が私が期待するものと一致していることに注意してください。私のライブラリが知らないエンコーディングルールがあるのでしょうか。

4

3 に答える 3

10

特定のUnicode文字は、合成および分解された形式で表すことができます。たとえば、ドイツ語のumlaut-uは、単一の文字またはその後に続くü文字のいずれかで表すことができ、テキストレンダラーはこれを組み合わせます。üu¨

厄介な詳細については、 Unicodeの等価性に関するウィキペディアの記事を参照してください。

したがって、Unicodeライブラリは通常、文字列をある形式または別の形式に正規化して比較できるようにするためのメソッドまたは関数を提供します。

于 2012-05-18T11:11:55.003 に答える
9
$ "\xC3\x83\xC2\xAB"
ë
$ use Encode

$ decode 'UTF-8', "\xC3\x83\xC2\xAB"
ë

UTF-8が二重にエンコードされています。Encode :: Repairは、これに対処する1つの方法です。

于 2012-05-18T11:19:21.907 に答える
3

(私はあなたの主題の質問に答えています、「同じ文字に対して2つの異なるUTF-8エンコーディングがありますか?」、これは投稿内の質問とは大きく異なります。)

(「文字」は通常、文字列要素を意味します。獣ではあいまいであり、ここで使用するのは適切な単語ではありません。視覚的表現であるグリフのUnicode用語は「書記素」です。)

はい、コードポイントのシーケンスが同じ書記素になる可能性がある以上のものがあります。たとえば、両方

U+00EB  LATIN SMALL LETTER E WITH DIAERESIS

U+0065  LATIN SMALL LETTER E
U+0308  COMBINING DIAERESIS

「ë」と表示されます。ブラウザの動作を見てみましょう。

  • U + 00EB:「ë」
  • U + 0065,0308:"ë"

UTF-8では、これらのコードポイントは次のようにエンコードされます。

  • U + 00EB:C3 AB
  • U + 0065:65
  • U + 0308:CC 88

Unicode :: Normalizeを使用するか、文字列を2つの形式のNFCいずれかに正規化します(選択)。NFD

$ perl -MUnicode::Normalize -E'
   $x = "\x{00EB}";
   $y = "\x{0065}\x{0308}";

   say     $x  eq     $y  ?1:0;
   say NFC($x) eq NFC($y) ?1:0;
   say NFD($x) eq NFD($y) ?1:0;
'
0
1
1

UTF-8には「オーバーロング」エンコーディングと呼ばれるものもあります。(具体的には、一般にUnicodeではなくUTF-8です。)UTF-8では、Unicodeコードポイントは次の4つのビットパターンのいずれかを使用してエンコードされます。

1 0xxxxxxx
2 110xxxxx 10xxxxxx
3 1110xxxx 10xxxxxx 10xxxxxx
4 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

「x」は、エンコードするコードポイントを表します。可能な限り短いものを使用する必要があるため、U+00EBは次のようになります。

0000 0000 1110 1011
      --- ---- ----

   -----   ------
110xxxxx 10xxxxxx
11000011 10101011
C3       AB

しかし、賢い人はそうするかもしれません

0000 0000 1110 1011
---- ---- ---- ----

    ----   ------   ------
1110xxxx 10xxxxxx 10xxxxxx
11100000 10000011 10101011
E0       83       AB

アプリケーションはE083ABを拒否する(または少なくともC3 ABに変換する)必要がありますが、拒否しないものもあり、セキュリティ上の問題を引き起こす可能性があります。PerlのEncodeモジュールはそのシーケンスを無効として扱うので、Perlの問題にはならないはずです。

于 2012-05-18T17:08:12.547 に答える