В чем смысл UTF-16?

Я никогда не понимал смысла кодировки UTF-16. Если вам нужно иметь возможность обрабатывать строки как случайный доступ (т. е. кодовая точка такая же, как и кодовая единица), вам нужен UTF-32, так как UTF-16 по-прежнему является переменной длиной. Если вам это не нужно, то UTF-16 кажется колоссальной тратой пространства по сравнению с UTF-8. Каковы преимущества UTF-16 перед UTF-8 и UTF-32 и почему Windows и Java используют его в качестве собственного кодирования?

5 ответов


при разработке Windows NT UTF-16 не существовало (NT 3.51 родился в 1993 году, в то время как UTF-16 родился в 1996 году со стандартом Unicode 2.0); вместо этого был UCS-2, которого в то время было достаточно для хранения каждого символа, доступного в Unicode, поэтому эквивалентность 1 кодовой точки = 1 кодовой единицы была фактически истинной - для строк не требовалась логика переменной длины.

Они перешли к UTF-16 позже, чтобы поддержать весь набор символов Юникода; однако они не могли перейти к UTF-8 или к UTF-32, потому что это нарушило бы двоичную совместимость в интерфейсе API (среди прочего).

как для Java, я не уверен; так как он был выпущен в ~1995 подозреваю, что UTF-16 был уже в воздухе (даже если это не стандартизированный пока), но я думаю, что совместимость с NT на основе операционной системы могут сыграть определенную роль в выборе (постоянный кодировке UTF-8 UTF-16 с конверсии для каждого вызова API-интерфейсов Windows можно ввести некоторые замедление.)


редактировать

Википедия объясняет, что даже для Java он пошел таким же образом: первоначально он поддерживал UCS-2, но перешел на UTF-16 в J2SE 5.0.

Итак, в общем, когда вы видите UTF-16, используемый в некотором API / Framework, это потому, что он начался как UCS-2 (чтобы избежать осложнений в алгоритмах управления строками), но он переместился в UTF-16 для поддержки кодовых точек за пределами BMP, все еще поддерживая тот же кодовый блок размер.


ни один из ответов, указывающих на преимущество UTF-16 над UTF-8, не имеет никакого смысла, за исключением ответа обратной совместимости.

Ну, есть два предостережения к моему комментарию.

Эрик заявляет: "UTF-16 охватывает весь BMP с одиночными единицами - поэтому, если у вас нет необходимости в более редких символах за пределами BMP, UTF-16 фактически составляет 2 байта на символ."

нюанс 1)

Если вы можете быть уверены, что ваше приложение никогда не понадобится любые символы вне BMP, и что любая библиотека кода, который вы пишете для использования с ним никогда не быть использован с любым приложением, которое будет когда-нибудь нужен персонаж вне БМП, то вы могли бы использовать UTF-16, и написать код, который делает неявное предположение, что каждый персонаж будет ровно два байта в длину.

Это кажется чрезвычайно опасным (на самом деле, глупо).

Если ваш код предполагает, что все символы UTF-16 в длину два байта, и ваша программа взаимодействует с приложением или библиотекой, где есть один символ за пределами BMP, тогда ваш код сломается. Код, который проверяет или манипулирует UTF-16, должен быть написан для обработки случая символа UTF-16, требующего более 2 байтов; поэтому я "отклоняю" это предостережение.

UTF-16 не проще кодировать, чем UTF-8 (код для обоих должен обрабатывать символы переменной длины).

нюанс 2)

UTF-16 может быть более вычислительно эффективным, под некоторые обстоятельства, если их правильно описать.

вот так: Предположим, что некоторые длинные строки редко изменяются, но часто исследуются (или лучше,никогда изменено после сборки-т. е. строитель строк, создающий немодифицируемые строки). Для каждой строки можно установить флаг, указывающий, содержит ли строка только символы "фиксированной длины" (т. е. не содержит символов, длина которых не равна двум байтам). Строки, для которых флаг true, могут быть рассмотрены с помощью оптимизированный код, который предполагает символы фиксированной длины (2 байта).

Как насчет космической эффективности?

UTF-16, очевидно, более эффективен для A) символов, для которых UTF-16 требует меньше байтов для кодирования, чем UTF-8.

UTF-8, очевидно, более эффективен для B) символов, для которых UTF-8 требует меньше байтов для кодирования, чем UTF-16.

за исключением очень "специализированного" текста, вероятно, что count(B) намного превышает count (A).


UTF-16 охватывает весь BMP с одиночными единицами-поэтому, если у вас нет необходимости в более редких символах вне BMP, UTF-16 фактически составляет 2 байта на символ. UTF-32 занимает больше места, UTF-8 требует поддержки переменной длины.


UTF16 обычно используется как прямое сопоставление с многобайтовыми наборами символов, т. е. Онил исходные 0-0xFFFF назначенные символы.

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


UTF-16 позволяет представлять все основные многоязычные плоскости (BMP) в виде отдельных кодовых единиц. Кодовые точки Юникода за пределами U+FFFF представлены суррогатными парами.

интересно то, что Java и Windows (и другие системы, использующие UTF-16) работают на уровне единицы кода, а не на уровне кодовой точки Unicode. Таким образом, строка, состоящая из одного символа U+1D122 (музыкальный символ F CLEF), кодируется в Java как "\ud824\udd22" и "\ud824\udd22".length() == 2 (не 1). Так это своего рода хак, но оказывается, что символы не имеют переменной длины.

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