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

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

7 ответов


в UTF-32 символ Юникода всегда будет представлен 4 байтами, поэтому синтаксический анализ кода будет легче написать, чем в строке UTF-16, потому что в UTF-16 символ представлен различным количеством байтов. Что касается недостатков в UTF-32 chatacter бы всегда требуется 4 байта, которые могут быть расточительными, если вы работаете в основном с английскими символами. Так свой выбор дизайна в зависимости от ваших требований ли использовать УТФ-16 или УТФ-32.


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

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


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

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

Copyright © 1991-2009 Unicode, Inc. Стандарт Unicode, Версия 5.2

на первый взгляд, UTF-32 кажется очевидным выбором форм кодирования Unicode для внутреннего кода обработки, потому что это форма кодирования фиксированной ширины. Он может быть conformantly привязан к 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 plat - forms, UTF-16 обеспечивает правильное сочетание компактного размера с возможностью обработки случайного символа вне формат BMP. UTF-32 имеет некоторое преимущество когда это прибывает в простотой конструкции и обслуживания кодирвоания програмного обеспечения. Поскольку обработка символов имеет фиксированную ширину, обработка UTF-32 не требует поддержания ветвей в программном обеспечении для тестирования и обработки элементов блока двойного кода, необходимых для дополнительных символов UTF-16. И наоборот, 32-разрядные индексы в больших таблицах не особенно эффективны для памяти. Чтобы избежать больших штрафов памяти таких индексов, таблицы Unicode часто обрабатывается как многоступенчатые таблицы (см. "многоступенчатые таблицы" в разделе 5.1, перекодирование в другие стандарты). В таких случаях 32-разрядные значения кодовых точек разрезаются на меньшие диапазоны, чтобы обеспечить сегментированный доступ к таблицам. Это верно даже в типичных реализациях UTF-32. Производительность UTF-32 в качестве кода обработки может быть фактически хуже, чем производительность UTF - 16 для тех же данных, потому что дополнительные накладные расходы памяти означают, что ограничения кэша будут превышаться чаще и память подкачка будет происходить чаще. Для систем с процессорным дизайном, которые налагают штрафы за 16-битный выровненный доступ, но имеют очень большую память, этот эффект может быть менее заметным. В любом случае кодовые точки Unicode не обязательно соответствуют ожиданиям пользователя для "символов"."Например, следующие не представлены одной кодовой точкой: комбинирующая последовательность символов, такая как ; объединяющая последовательность jamo для корейского языка; или конъюнкт Devanagari "ksha."Потому что некоторые Unicode text pro- обработка должна знать и обрабатывать такие последовательности символов, как текстовые элементы, преимущество формы кодирования с фиксированной шириной UTF-32 несколько компенсируется природой обработки текстовых элементов с различной шириной. См. технический стандарт Unicode #18, "регулярные выражения Uni - кода", например, где обычно реализуемые процессы имеют дело с текстовыми элементами переменной ширины из-за ожиданий пользователя идентичности символа." UTF-8. UTF-8 имеет достаточно компактные количество используемых байтов. Это действительно только при значительном недостатке размера при использовании для восточноазиатских реализаций, таких как Чи - несе, японский и корейский, которые используют идеограммы Хань или слоги хангыля, требующие трехбайтовых кодовых последовательностей в UTF - 8. UTF-8 также значительно менее эффективен с точки зрения обработки, чем другие формы кодирования. Бинарная Сортировка. Двоичный вид строк UTF-8 дает тот же порядок, что и двоичный вид кодовых точек Unicode. Это очевидно тот же порядок, что и для двоичного вида строк UTF-32.

Общие Структуры

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


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

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

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


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

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

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

char getChar(int index, String s );

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

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


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

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

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

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


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

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