Какой смысл UTF-16?

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

Ответ 1

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

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

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


Edit

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

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

Ответ 2

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

Ну, в мой комментарий есть два оговорки.

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

Предостережение 1)

Если вы можете быть уверены, что вашему приложению никогда не понадобится какой-либо символ вне BMP, и что любой код библиотеки, который вы пишете для использования с ним, НИКОГДА не будет использоваться с любым приложением, которое когда-либо понадобится персонажу вне BMP, тогда вы можете использовать UTF-16 и писать код, который делает неявное предположение, что каждый символ будет иметь ровно два байта в длину.

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

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

Поэтому код, который исследует или обрабатывает 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.

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

Ответ 3

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

Ответ 4

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

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

Ответ 5

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

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

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