Может ли быть 2 разных кодировки UTF-8 для одного и того же символа?

Я пишу приложение, которое должно перекодировать свой ввод из UTF-8 в ISO-8859-1 (латиница 1).

Все работает отлично, за исключением того, что иногда я получаю странные кодировки для некоторых умлаутовых символов. Например, латинская 1 E с 2 точками (0xEB) обычно обозначается как UTF-8 0xC3 0xAB, но иногда также как 0xC3 0x83 0xC2 0xAB.

Это происходило несколько раз из разных источников, и, учитывая, что первый и последний символы соответствуют ожидаемым, может ли существовать правило кодирования, о котором моя библиотека не знает?

Ответы на вопрос(3)

Состоит а также Разложившийся форма. Например, немецкий умлаут-уü может быть представлен либо одним символомü илиu с последующим¨, который затем объединит текстовый рендер.

См. Статью в Википедии на Юникодная эквивалентность для кровавых подробностей.

аким образом, библиотеки @Unicode обычно предоставляют методы или функции для нормализации строк в той или иной форме, чтобы вы могли сравнить их.

 Ozair Kafray18 мая 2012 г., 13:13
+ 1 Этого я не знал даже после прочтения: Joelonsoftware.com / статьи / Unicode.html
 DarkDust18 мая 2012 г., 13:19
@ daxim: как так? Он спросил о правиле кодирования, и я сказал ему об этом.
 cjm18 мая 2012 г., 20:45
@ DarkDust, он спросил о 0xC3 0x83 0xC2 0xAB, представляющих ë. Это не разложенная форма; это двойная кодировка.
 daxim18 мая 2012 г., 13:17
-1 Этот ответ не подходит для проблемы, с которой сталкивается Джин Винсент.
Решение Вопроса
$ "\xC3\x83\xC2\xAB"
ë
$ use Encode

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

Encode :: Ремонт это один из способов справиться с этим.

Может ли быть 2 разных кодировки UTF-8 для одного и того же символа? ", что существенно отличается от вопроса внутри поста.)

(«Символ» обычно означает строковый элемент. У зверя это неоднозначно, и это неправильное слово для использования здесь. Термин Юникод для визуального представления, глиф, это «графема».)

Да, существует более чем последовательность кодовых точек, которые могут привести к одной и той же графеме. Например, оба

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 :: Нормализовать sNFC или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 также есть кое-что, называемое «слишком длинными» кодировками. (В частности, UTF-8, а не Unicode в целом.) В UTF-8 кодовые точки Unicode кодируются с использованием одной из четырех следующих битовых комбинаций:

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

Applications должны отклонить E0 83 AB (или, по крайней мере, преобразовать его в C3 AB), но некоторые этого не делают, и это может вызвать проблемы с безопасностью. Модуль Encode в Perl рассматривает эту последовательность как недопустимую, поэтому для Perl это не должно быть проблемой.

 ikegami18 мая 2012 г., 19:14
@ daxim, принимая ответы, которые не соответствуют проблеме, на совершенно новый уровень

Ваш ответ на вопрос