Почему UTF-32 вместо UTF-16, если у нас есть суррогатные пары? - PullRequest
14 голосов
/ 09 марта 2009

Если я правильно понимаю, UTF-32 может обрабатывать каждого персонажа во вселенной. Так может UTF-16, с помощью суррогатных пар. Так есть ли веская причина использовать UTF-32 вместо UTF-16?

Ответы [ 7 ]

9 голосов
/ 09 марта 2009

В UTF-32 символ Unicode всегда будет представлен 4 байтами, поэтому код синтаксического анализа будет легче написать, чем код строки UTF-16, потому что в UTF-16 символ представлен различным количеством байтов. С другой стороны, для чата UTF-32 всегда требуется 4 байта, что может быть расточительным, если вы работаете в основном с английскими символами. Поэтому выбор дизайна зависит от ваших требований, использовать ли UTF-16 или UTF-32.

8 голосов
/ 09 марта 2009

Кто-то может предпочесть иметь дело с UTF-32 вместо UTF-16, потому что работа с суррогатными парами почти всегда обрабатывает «особые случаи», а необходимость иметь дело с этими особыми случаями означает, что у вас есть области, в которых могут появляться ошибки потому что вы имеете дело с ними неправильно (или, скорее, просто забудете иметь дело с ними вообще).

Если увеличенное использование памяти UTF-32 не является проблемой, уменьшенная сложность может быть достаточным преимуществом для его выбора.

5 голосов
/ 19 июля 2010

Вот хорошая документация от Консорциума Unicode.

Сравнение преимуществ UTF-32, UTF-16 и UTF-8

Copyright © 1991–2009 Unicode, Inc. Стандарт Юникод, версия 5.2

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

UTF-32 и UTF-16. В среднем, более 99 процентов всех данных UTF-16 выражаются в единичных единицах кода. Это включает в себя почти все типичные символы, которые программное обеспечение должно обрабатывать с помощью специальных операций над текстом, например, символы управления форматом. Как следствие, большинству операций сканирования текста вообще не нужно распаковывать суррогатные пары UTF-16, а можно безопасно обрабатывать их как непрозрачную часть строки символов. Для многих операций UTF-16 так же легко обрабатывать, как и UTF-32, а производительность UTF-16 в качестве кода обработки имеет тенденцию быть достаточно хорошей. UTF-16 - это код выбора внутренней обработки для большинства реализаций, поддерживающих Unicode. Кроме платформ Unix, UTF-16 обеспечивает правильное сочетание компактных размеров с возможностью обрабатывать случайные символы вне BMP. UTF-32 имеет некоторое преимущество, когда речь идет о простоте разработки и сопровождения программного кодирования. Поскольку обработка символов имеет фиксированную ширину, обработка UTF-32 не требует поддержки ветвей в программном обеспечении для тестирования и обработки элементов с двойным кодовым блоком, необходимых для дополнительных символов UTF-16. И наоборот, 32-битные индексы в больших таблицах не особенно эффективны для памяти. Чтобы избежать больших потерь памяти таких индексов, таблицы Unicode часто обрабатываются как многоступенчатые таблицы (см. «Многоступенчатые таблицы» в Разделе 5.1, Транскодирование в другие стандарты). В таких случаях 32-битные значения кодовой точки делятся на меньшие диапазоны, чтобы обеспечить сегментированный доступ к таблицам. Это верно даже в типичных реализациях UTF-32. Производительность UTF-32 в качестве кода обработки на самом деле может быть хуже, чем производительность UTF-16 для тех же данных, потому что дополнительные накладные расходы памяти означают, что ограничения кеша будут превышаться чаще, а подкачка памяти будет происходить чаще. Для систем с процессорами, которые налагают штрафы за 16-битный выравниваемый доступ, но имеют очень большую память, этот эффект может быть менее заметным. В любом случае кодовые точки Unicode не обязательно соответствуют ожиданиям пользователя в отношении «символов». Например, следующее не представлено одной кодовой точкой: комбинация символьной последовательности, такая как; последовательность джамо для корейского; или конъюнкт Деванагари «ksha». Поскольку некоторая обработка текста в Юникоде должна учитывать такие последовательности символов и обрабатывать их как текстовые элементы, преимущество UTF-32 в форме кодирования с фиксированной шириной несколько компенсируется присущей ему переменной. Характер ширины обработки текстовых элементов. См. Технический стандарт Unicode № 18 «Регулярные выражения Unicode», где приведен пример, в котором обычно реализуемые процессы имеют дело с текстовыми элементами по своей природе переменной ширины из-за ожиданий пользователя в отношении идентичности «символа». UTF-8. UTF-8 - это причинаbly compact с точки зрения количества используемых байтов. На самом деле он имеет только существенный недостаток в размере, когда используется для восточноазиатских реализаций, таких как китайский, японский и корейский, которые используют идеограммы Хань или слоги хангыль, требующие трехбайтовых последовательностей кодовых единиц в UTF-8. UTF-8 также значительно менее эффективен с точки зрения обработки, чем другие формы кодирования. Бинарная сортировка. Бинарная сортировка строк UTF-8 дает тот же порядок, что и двоичная сортировка кодовых точек Юникода. Это, очевидно, тот же порядок, что и для двоичной сортировки строк UTF-32.

Общая структура

Все три формы кодирования дают одинаковые результаты для сравнения двоичных строк или сортировки строк при работе только с символами BMP (в диапазоне U + 0000..U + FFFF). Однако при работе с дополнительными символами (в диапазоне U + 10000..U + 10FFFF) двоичный порядок UTF-16 не соответствует порядку кодовых точек Unicode. Это может привести к осложнениям при попытке взаимодействия с двоичными отсортированными списками, например, между системами UTF-16 и системами UTF-8 или UTF-32. Однако для данных, которые отсортированы в соответствии с условностями конкретного языка или локали, а не с использованием двоичного порядка, данные будут упорядочены одинаково, независимо от формы кодирования.

3 голосов
/ 09 марта 2009

Вероятно, есть несколько веских причин, но одна из них заключается в ускорении индексации / поиска, т. Е. В базах данных и т. П.

С UTF-32 вы знаете, что каждый символ составляет 4 байта. С UTF-16 вы не знаете, какой длины будет конкретный символ.

Например, у вас есть функция, которая возвращает n-й символ строки:

char getChar(int index, String s );

Если вы кодируете на языке, который имеет прямой доступ к памяти, скажем, C, то в UTF-32 эта функция может быть такой же простой, как арифметика некоторого указателя (s+(4*index)), которая будет иметь некоторые значения O (1).

Однако если вы используете UTF-16, вам придется пройтись по строке, расшифровав ее по ходу, что будет O (n).

3 голосов
/ 09 марта 2009

Краткий ответ: нет.

Более длинный ответ: да, для совместимости с другими вещами, которые не получили памятку.

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

2 голосов
/ 19 июля 2010

Как правило, вы просто используете строковый тип данных / кодировку базовой платформы, которая часто (Windows, Java, Cocoa ...) UTF-16 и иногда UTF-8 или UTF-32. Это в основном по историческим причинам; между тремя кодировками Unicode есть небольшая разница: все три четко определены, быстрые и надежные, и все они могут кодировать каждую последовательность кодовых точек Unicode. Уникальная особенность UTF-32 в том, что это кодирование с фиксированной шириной (то есть каждая кодовая точка представлена ​​ровно одной кодовой единицей), практически бесполезна: ваш уровень управления памятью должен знать о количестве и ширине кода юниты, а пользователи интересуются абстрактными символами и графемами. Как упомянуто в стандарте Unicode, приложения Unicode в любом случае должны иметь дело с комбинированными символами, лигатурами и т. Д., И обработка суррогатных пар, несмотря на то, что они концептуально различаются, может выполняться в одной и той же технической структуре.

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

2 голосов
/ 09 марта 2009

UTF-8 также может представлять любой символ юникода!

Если ваш текст в основном английский, вы можете сэкономить много места, используя utf-8, но индексирование символов - это не O (1), потому что некоторые символы занимают больше, чем один байт.

Если пространство не так важно для вашей ситуации, как скорость, utf-32 подойдет вам лучше, потому что индексирование равно O (1)

UTF-16 может быть лучше, чем utf-8 для неанглийского текста, потому что в utf-8 возникает ситуация, когда некоторые символы занимают 3 байта, тогда как в utf16 они занимают только два байта.

...