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

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

61 голосов
/ 13 марта 2011

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

Ответы [ 5 ]

47 голосов
/ 13 марта 2011

Когда Windows NT была разработана, UTF-16 не существовало (NT 3.51 родилась в 1993 году, а UTF-16 родилась в 1996 году со стандартом Unicode 2.0);вместо этого был UCS-2, которого на тот момент было достаточно для хранения каждого символа, доступного в Юникоде, поэтому эквивалентность 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 в J2SE5.0.

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

18 голосов
/ 05 января 2014

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

Ну, есть два замечания для моего комментария.

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

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

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

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

3 голосов
/ 13 марта 2011

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

1 голос
/ 13 марта 2011

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

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

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

1 голос
/ 13 марта 2011

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...