2012-01-23 2 views
1

У меня строка в Юникоде, закодированная, скажем, как UTF8. Одна строка в Unicode может иметь несколько байтовых представлений. Интересно, существует ли какая-либо каноническая (нормированная) форма строки Unicode или может быть создана, и мы можем, например, сравнивают такие строки с memcmp(3) и т. д. Может, например, ICU или любая другая библиотека C/C++?Каноническая форма строки Юникода

+0

У Glib есть [unicode manipulation] (http://developer.gnome.org/glib/2.30/glib-Unicode-Manipulation.html) объект. ['g_utf8_collate'] (http://developer.gnome.org/glib/2.30/glib-Unicode-Manipulation.html#g-utf8-collate), может быть? –

+0

http://userguide.icu-project.org/transforms/normalization –

+0

Вопрос слишком расплывчатый.Пожалуйста, определите, что вы подразумеваете под «Одна строка в Unicode может иметь несколько байтовых представлений», предпочтительно иллюстрируя ее примерами. Если кодировка определенно UTF-8, и это примерно последовательность символов Юникода, то такой возможности нет. –

ответ

6

Возможно, вы ищете Unicode normalisation. Существуют, по существу, четыре различные нормальные формы, каждая из которых гарантирует, что все эквивалентные строки имеют общую форму впоследствии. Тем не менее, во многих случаях вам нужно также учитывать языковой стандарт, поэтому, хотя это может быть дешевым способом сравнения байт-байт (если вы обеспечиваете такой же формат преобразования Юникод, как UTF-8 или UTF-16 и такая же нормальная форма), это не принесет вам много преимуществ от этого ограниченного варианта использования.

+0

Хорошо, допустим, что существует гораздо больше сравнений, чем время, необходимое для выяснения канонической формы строк. Не могли бы вы тогда рассмотреть нормализацию как хороший способ? – Cartesius00

+0

Канонизация довольно быстрая. Многие кодеки не меняются вообще. Единственная сложная часть заключается в том, хотите ли вы рассматривать «Æ» как «AE». – MSalters

+0

MSalters: 'Æ' не имеет разбиения. – Joey

2

Сравнение Unicode последовательности: элемент кода

UTF-8 является само каноническое представление. Две строки Юникода, которые состоят из одних и тех же кодовых точек Юникода, всегда будут кодироваться в точно такую ​​же последовательность байтов UTF-8 и поэтому могут быть сопоставлены с memcmp. Это необходимое свойство кодировки UTF-8, в противном случае это было бы нелегко декодировать. Но мы можем пойти дальше, это верно для всех официальных схем кодирования Unicode, UTF-8, UTF-16 и UTF-32. Они кодируют строку в разные последовательности байтов, но они всегда кодируют одну и ту же строку в одну и ту же последовательность. Если вы рассматриваете сущность и независимость платформы, UTF-8 является рекомендуемой схемой кодирования, потому что вам не нужно иметь дело с порядками байтов при чтении или записи 16-битных или 32-битных значений.

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

Сравнение строк Unicode:

Там есть другая проблема, гораздо сложнее справиться. В Юникоде некоторые глифы (символ, который вы видите на экране или на бумаге) могут быть представлены одним кодовым числом или комбинацией из двух последовательных кодовых точек (, объединяющих символы). Обычно это относится к глифам с акцентами, диакритическими знаками и т. Д. Из-за различного представления кодовых точек их соответствующая последовательность байтов будет отличаться. Сравнение строк при учете этих комбинированных символов не может быть выполнено с простым сравнением байтов, сначала вы должны его нормализовать.

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

+0

Чтобы развернуть комментарии о объединении символов, чтобы сравнить такие строки, вы «нормализуете» строку кодовых точек. Ищите форму формульной формы (NFC) или разложенную форму нормализации (NFD). Существуют также форматы нормализации совместимости NFCK и NFDK. Однако есть еще и сравнение строк. Например, если вы хотите игнорировать случай на языках, которые имеют дело с фальцованием, а на других языках есть другие вещи, которые вам нужно учитывать. – bames53

+1

Хотя это звучит разумно, на самом деле это не то, как Юникод. UTF-8 является каноническим представлением кодовых точек, да, но вопрос был о строках. Ваш PS. не является постскриптумом, но является основной проблемой в локальных независимых сравнения строк. (Локально-зависимые и/или нечувствительные к строкам сравнения строк - это еще одно дело, но, вероятно, здесь не имеет значения - уже упоминавшийся вопрос «memcmp».) – MSalters

+0

Вы оба правы. Кажется, я не понял эту часть вопроса. – buc

1

Вы хотите нормализовать строку в одной из форм нормализации Unicode. libicu может сделать это для вас, но не для строки UTF-8. Вы должны сначала преобразовать его в UChar, используя, например, ucnv_toUChars, затем нормализуйтесь с помощью unorm_normalize, затем конвертируйте обратно с помощью ucnv_fromUChars. Я думаю, что есть также определенная версия ucnv_ * для кодировки UTF-8.

Если memcmp является вашей единственной целью, вы можете, конечно, сделать это непосредственно на массиве UChar после unorm_normalize.

+0

Что такое unorm_normalize? – jjxtra

+0

Это функция libicu. http://www.icu-project.org/apiref/icu4c/unorm_8h.html#a5410fab40c4e60a787c5cfbea5103c75 –