Что такое нормализованный UTF-8?



The проект ICU (который также теперь имеет PHP библиотека) содержит классы, необходимые для нормализации строк UTF-8, чтобы упростить сравнение значений при поиске.



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

728   7  

7 ответов:

все, что вы никогда не хотели знать о нормализации Unicode

Каноническая Нормализация

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

При Использовании

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

каноническая нормализация поставляется в 2 формах: NFD и NFC. Они эквивалентны в том смысле, что можно конвертировать между этими двумя формами без потерь. Сравнение двух строк под NFC всегда даст тот же результат, что и сравнение их под NFC НФД.

NFD

nfd имеет символы полностью развернуты. Это более быстрая форма нормализации для вычисления, но результаты в большем количестве кодовых точек (т. е. использует больше пространства).

если вы просто хотите сравнить две строки, которые еще не нормализованы, это предпочтительная форма нормализации, если вы не знаете, что вам нужна нормализация совместимости.

NFC

NFC рекомбинирует кодовые точки, когда это возможно после запуска NFD алгоритм. Это занимает немного больше времени, но приводит к более коротким строкам.

Нормализация Совместимости

Unicode также включает в себя множество символов, которые действительно не принадлежат, но были использованы в устаревших наборах символов. Unicode добавил их, чтобы текст в этих наборах символов обрабатывался как Unicode, а затем преобразовывался обратно без потери.

нормализация совместимости преобразует их в соответствующую последовательность "реальных" символов, а также выполняет каноническую нормализацию. Результаты нормализации совместимости могут не совпадать с оригиналами.

символы, содержащие информацию о форматировании, заменяются символами, которые этого не делают. Например, символ преобразуется к виду 9. Другие не связаны с различиями форматирования. Например, Римская цифра преобразуется в обычные буквы IX.

очевидно, как только это преобразование было это уже невозможно без потерь преобразовать обратно в исходный набор символов.

при использовании

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

отличным вариантом использования будет поисковая система, так как вы, вероятно, захотите найти 9 в матче .

одна вещь, которую вы, вероятно, не должны делать, это отображать результат применения нормализации совместимости к пользователю.

NFKC / NFKD

форма нормализации совместимости поставляется в двух формах NFKD и NFKC. Они имеют те же отношения, что и между NFD и C.

любая строка в NFKC по своей сути также находится в NFC, и то же самое для NFKD и NFD. Таким образом NFKD(x)=NFD(NFKC(x)) и NFKC(x)=NFC(NFKD(x)) и т. д.

вывод

если есть сомнения, идите с канонической нормализацией. Выберите NFC или NFD на основе применимого компромисса пространства/скорости или на основе того, что требуется для чего-то, с чем вы взаимодействуете.

некоторые символы, например буквы с ударением (например, é) можно представить двумя способами-одной кодовой точкой U+00E9 или простая буква, за которой следует комбинированный знак ударения U+0065 U+0301. Обычная нормализация выберет один из них, чтобы всегда представлять его (Единая кодовая точка для NFC, объединяющая форма для NFD).

для символов, которые могут быть представлены несколькими последовательностями базовых символов и объединяющими метками (скажем, "s, точка ниже, точка выше" vs поставив точку выше, затем точку ниже или используя базовый символ, который уже имеет одну из точек), NFD также выберет один из них (ниже идет первым, как это происходит)

декомпозиции совместимости включают в себя ряд символов, которые "не должны быть символами", но потому, что они использовались в устаревших кодировках. Обычная нормализация не объединит их (чтобы сохранить целостность туда и обратно - это не проблема для комбинирующих форм, потому что нет устаревшей кодировки [кроме нескольких вьетнамских кодировок] используются оба), но нормализация совместимости будет. Подумайте, как знак килограмма "кг", который появляется в некоторых восточноазиатских кодировках (или полуширина/полная ширина катаканы и алфавита), или лигатура" fi " в MacRoman.

см.http://unicode.org/reports/tr15/ для более подробной информации.

нормальные формы (Unicode, а не базы данных) имеют дело в первую очередь (исключительно?) с символами, которые имеют диакритические знаки. Unicode предоставляет некоторые символы со "встроенными" диакритическими знаками, такими как U+00C0, "Латинская заглавная A с могилой". Один и тот же символ может быть создан из" латинского заглавия A "(U+0041) с" сочетанием серьезного акцента " (U+0300). Это означает, что даже если две последовательности производят один и тот же результирующий характер, побайтовое сравнение покажет их как полностью отличающийся.

нормализация-это попытка справиться с этим. Нормализация гарантирует (или, по крайней мере, пытается), что все символы кодируются одинаково-либо все с использованием отдельной комбинирующей диакритической метки, где это необходимо, либо все с использованием одной кодовой точки, где это возможно. С точки зрения сравнения, это действительно не имеет большого значения, что вы выбираете - почти любая нормализованная строка будет правильно сравниваться с другой нормализованной строкой.

в этом случай, "совместимость" означает совместимость с кодом, который предполагает, что одна точка кода равна одному символу. Если у вас есть такой код, вы, вероятно, хотите использовать нормальную форму совместимости. Хотя я никогда не видел, чтобы это было указано напрямую, названия обычных форм подразумевают, что консорциум Unicode считает предпочтительным использовать отдельные комбинирующие диакритические знаки. Это требует большего интеллекта для подсчета фактических символов в строке (а также таких вещей, как разрыв строки интеллигентно), но более разносторонне.

Если вы полностью используете ICU, скорее всего, вы хотите использовать каноническую нормальную форму. Если вы пытаетесь написать код самостоятельно, который (например) предполагает, что точка кода равна символу, то вам, вероятно, нужна нормальная форма совместимости, которая делает это как можно чаще.

Если две строки Юникода канонически эквивалентны, строки действительно одинаковы, только с использованием разных последовательностей Юникода. Например, Ä может быть представлено либо используя Ä символ или комбинация и ◌.

Если строки эквивалентны только совместимости, строки не обязательно одинаковы, но они могут быть одинаковыми в некоторых контекстах. Например, ff можно считать таким же, как ff.

Итак, если вы сравниваете строки, вы должны использовать canonical эквивалентность, потому что эквивалентность совместимости не является реальной эквивалентностью.

но если вы хотите отсортировать набор строк, возможно, имеет смысл использовать эквивалентность совместимости, поскольку они почти идентичны.

является ли каноническая эквивалентность или эквивалентность совместимости более актуальной для вас, зависит от вашего приложения. Способ ASCII мышления о сравнении строк примерно соответствует канонической эквивалентности, но Unicode представляет собой множество языков. Я не думаю, что можно с уверенностью предположить, что Unicode кодирует все языки таким образом, что позволяет рассматривать их так же, как западноевропейский ASCII.

цифры 1 и 2 приведите хорошие примеры двух типов эквивалентность. В соответствии с эквивалентностью совместимости, похоже, что одно и то же число в суб - и супер - скриптовой форме будет сравниваться равным. Но я не уверен, что решить ту же проблему, что и курсивная арабская форма или повернутые символы.

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

это на самом деле довольно проста. UTF-8 на самом деле имеет несколько различных представлений одного и того же "персонажа". (Я использую символ в кавычках, так как по байтам они разные, но практически они одинаковы). Пример приведен в связанном документе.

символ " Ç " может быть представлен в виде последовательности байтов 0xc387. Но он также может быть представлен в виде C (0x43), за которым следует последовательность байтов 0x8ccca7. Таким образом, вы можете сказать, что 0xc387 и 0x438ccca7 одинаковы характер. Причина, которая работает, заключается в том, что 0x8ccca7 является комбинирующим знаком; то есть он принимает символ перед ним (a C здесь), и изменяет его.

есть 2 типа символов, те, которые передают смысл через стоимостью, и те, которые берут другой символ и изменяют его. Так что 9 имеет смысл характер. Супер-скрипт ⁹ принимает это значение и изменяет его с помощью презентации. Таким образом, канонически они имеют разные значения, но они все еще представляют базовый характер.

надеюсь, что это поможет...

проблема сравнивать строки: две строки с содержимым, эквивалентным для большинства приложений, могут содержать различные последовательности символов.

посмотреть каноническая эквивалентность Юникода: если алгоритм сравнения прост (или должен быть быстрым), то эквивалентности Юникод не выполнено. Эта проблема возникает, например, в каноническом сравнении XML, см. http://www.w3.org/TR/xml-c14n

чтобы избежать этой проблемы... Какой стандарт использовать? "расширенной кодировке utf8" или "в компактном формате utf8"?
Используйте "ç" или " c+◌."?

W3C и другие (например. имена файлов) предложите использовать "составленный как канонический "(имейте в виду C" самых компактных " более коротких строк)... Итак,

стандарт C! в сомнении использовать NFC

для взаимодействия, и для "соглашение по конфигурации" выбор рекомендуется использовать NFC, чтобы "канонизировать" внешние строки. Для хранения канонического XML, например, сохраните его в"FORM_C". От организации W3C CSV в Сети рабочая группа также рекомендую NFC (раздел 7.2).

PS: de "FORM_C" - это формы по умолчанию в большинстве библиотек. Бывший. в нормализаторе PHP.isnormalized ().


Ther термин "композиция форма" (FORM_C) используется как для того, чтобы сказать, что "строка находится в C-канонической форме" (результат преобразования NFC), так и для того, чтобы сказать, что используется алгоритм преобразования... Смотрите http://www.macchiato.com/unicode/nfc-faq

(...) каждая из следующих последовательностей (первые две являются односимвольными последовательностями) представляют один и тот же символ:

  1. U + 00C5 (Å ) ЛАТИНСКАЯ ЗАГЛАВНАЯ БУКВА A С КОЛЬЦОМ Выше
  2. U+212B ( Å ) ЗНАК АНГСТРЕМА
  3. U + 0041 (A ) ЛАТИНСКАЯ ЗАГЛАВНАЯ БУКВА A + U+030A () КОМБИНИРУЯ КОЛЬЦО ВЫШЕ

эти последовательности называются канонически эквивалентны. Первая из этих форм называется NFC-for Normalization Form C, где C - для композиция. (...) Функция, преобразующая строку S в форму NFC, может быть сокращена как toNFC(S), в то время как тот, который проверяет, находится ли S В NFC, сокращается как isNFC(S).


Примечание: для проверки нормализации маленьких строк (чистые ссылки на UTF-8 или XML-сущности) вы можете использовать этот тест / нормализация онлайн конвертер.

Comments

    Ничего не найдено.