Там какая-либо причина состоит в том, чтобы предпочесть UTF-16 по UTF-8?

Исследуя атрибуты UTF-16 и UTF-8, я не могу найти причину предпочесть UTF-16.

Однако проверяя Java и C#, это похоже на строки и символы там значение по умолчанию к UTF-16. Я думал, что это могло бы быть по историческим причинам, или возможно по причинам производительности, но не могло найти информацию.

Кто-либо знает, почему эти языки выбрали UTF-16? И есть ли какая-либо допустимая причина для меня сделать это также?

Править: Между тем я также нашел этот ответ, который кажется релевантным и имеет некоторые интересные ссылки.

28
задан Community 23 May 2017 в 10:31
поделиться

6 ответов

Для восточноазиатских языков обычно требуется меньше памяти в UTF-16 (2 байта достаточно для 99% символов восточно-азиатских языков), чем в UTF-8 (обычно требуется 3 байта).

Конечно, для западных языков UTF-8 обычно меньше (1 байт вместо 2). Для смешанных файлов, таких как HTML (где много разметки), это большая проблема.

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

32
ответ дан 28 November 2019 в 03:03
поделиться

Я представляю C # использование UTF-16 происходит от семейства операционных систем Windows NT, использующих UTF-16 для внутренних целей.

Я полагаю, что есть две основные причины, по которым Windows NT использует UTF-16 внутри себя:

  • Для использования памяти: UTF-32 тратит впустую лот места для кодирования.
  • Для производительности: UTF-8 намного сложнее декодировать, чем UTF-16. В UTF-16 символы либо базовый многоязычный плоский символ (2 байта) или суррогат Пара (4 байта). Символы UTF-8 может быть от 1 до 4 байтов.

Вопреки тому, что ответили другие люди, вы не можете рассматривать UTF-16 как UCS-2 . Если вы хотите правильно перебирать фактические символы в строке, вы должны использовать функции итерации, удобные для юникода. Например, в C # вам нужно использовать StringInfo.GetTextElementEnumerator () .

Для получения дополнительной информации стоит прочитать эту страницу вики: http: //en.wikipedia.org / wiki / Comparison_of_Unicode_encodings

7
ответ дан 28 November 2019 в 03:03
поделиться

UTF-16 может быть более эффективным для представления символов на некоторых языках, таких как китайский, японский и корейский, где может быть представлено большинство символов одним 16-битным словом. Для некоторых редко используемых символов может потребоваться два 16-битных слова. UTF-8, как правило, намного более эффективен для представления символов из наборов символов Западной Европы - UTF-8 и ASCII эквивалентны в диапазоне ASCII (0-127) - но менее эффективен с азиатскими языками, требуя трех или четырех байтов для представления символов, которые может быть представлен двумя байтами в UTF-16.

UTF-16 имеет преимущество в качестве формата в памяти для Java / C # в том, что каждый символ в базовой многоязычной плоскости может быть представлен в 16-битном формате (см. Ответ Джо) и некоторые недостатки UTF-16 (например, запутывающий код, использующий терминаторы \ 0) менее актуальны.

3
ответ дан 28 November 2019 в 03:03
поделиться

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

Таким образом, вы избежите всех сложностей кодировок переменной длины, таких как UTF-8.

2
ответ дан 28 November 2019 в 03:03
поделиться

@Oak: это слишком длинно для комментария...

Я не знаю насчет C# (и был бы очень удивлен: это означало бы, что они просто скопировали Java слишком много), но для Java все просто: Java была задумана до выхода Unicode 3.1.

Следовательно, было меньше 65537 кодовых точек, следовательно, каждая кодовая точка Unicode все еще помещалась в 16-битный формат, и так родилась Java char.

Конечно, это привело к сумасшедшим проблемам, которые все еще влияют на Java-программистов (как я) сегодня, где у вас есть метод charAt, который в некоторых случаях не возвращает ни символ Unicode, ни кодовую точку Unicode, и метод (добавленный в Java 5) codePointAt, который принимает аргумент, который не является числом кодовых точек, которые вы хотите пропустить! (вы должны передать в codePointAt количество Java char, которые вы хотите пропустить, что делает этот метод одним из наименее понятных в классе String).

Итак, да, это определенно дико и сбивает с толку большинство программистов Java (большинство даже не в курсе этих проблем) и, да, это имеет историческую причину. По крайней мере, это было оправдание, которое придумали, когда люди разозлились после этого вопроса: но это потому, что Unicode 3.1 еще не вышел.

:)

10
ответ дан 28 November 2019 в 03:03
поделиться

Это зависит от ожидаемых наборов символов. Если вы ожидаете интенсивного использования кодовых точек Unicode за пределами 7-битного диапазона ASCII, вы можете обнаружить, что UTF-16 будет более компактным, чем UTF-8, поскольку некоторые последовательности UTF-8 имеют длину более двух байтов.

Кроме того, из соображений эффективности Java и C # не принимают во внимание суррогатные пары при индексировании строк. Это полностью нарушится при использовании кодовых точек, представленных последовательностями UTF-8, занимающими нечетное количество байтов.

3
ответ дан 28 November 2019 в 03:03
поделиться