Отличаются ли UTF-8, UTF-16 и UTF-32 количеством символов, которые они могут хранить?

Хорошо. Я знаю, что это выглядит как типичное "Почему он просто не прогуглил его или не зашел на http://www.unicode.org/ и не нашел его?" вопрос, но для такого простого вопроса ответ все еще ускользает от меня после проверки обоих источников.

Я почти уверен, что все три системы кодирования поддерживают все символы Unicode, но мне нужно подтвердить это, прежде чем я сделаю это в презентации.

Дополнительный вопрос: отличаются ли эти кодировки количеством символов, которые они могут расширять для поддержки?

6 ответов

Решение

Нет, это просто разные методы кодирования. Все они поддерживают кодирование одного и того же набора символов.

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

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

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

http://en.wikipedia.org/wiki/Comparison_of_Unicode_encodings

Не существует символа Unicode, который может быть сохранен в одной кодировке, но не в другой. Это просто потому, что допустимые символы Unicode были ограничены тем, что может быть сохранено в UTF-16 (который имеет наименьшую емкость из трех кодировок). Другими словами, UTF-8 и UTF-32 могут использоваться для представления более широкого диапазона символов, чем UTF-16, но это не так. Читайте дальше для более подробной информации.

UTF-8,

UTF-8 - это код переменной длины. Некоторые символы требуют 1 байт, некоторые требуют 2, некоторые 3 и некоторые 4. Байты для каждого символа просто записываются один за другим как непрерывный поток байтов.

Хотя некоторые символы UTF-8 могут иметь длину 4 байта, UTF-8 не может кодировать 2^32 символа. Это даже не близко. Я постараюсь объяснить причины этого.

Программное обеспечение, которое считывает поток UTF-8, просто получает последовательность байтов - как это должно решить, являются ли следующие 4 байта единственным 4-байтовым символом, или двумя 2-байтовыми символами, или четырьмя 1-байтовыми символами (или какая-то другая комбинация)? По сути, это делается путем принятия решения о том, что определенные 1-байтовые последовательности не являются допустимыми символами, а некоторые 2-байтовые последовательности не являются допустимыми символами и т. Д. Когда появляются эти недопустимые последовательности, предполагается, что они образуют часть более длинной последовательности.

Я уверен, что вы видели совсем другой пример этого: это называется побег. Во многих языках программирования решено, что \ символ в исходном коде строки не переводится в любой допустимый символ в "скомпилированной" форме строки. Когда \ находится в источнике, предполагается, что он является частью более длинной последовательности, например \n или же \xFF, Обратите внимание, что \x является недопустимой 2-символьной последовательностью и \xF является недопустимой 3-символьной последовательностью, но \xFF является допустимой 4-символьной последовательностью.

По сути, существует компромисс между количеством символов и более короткими символами. Если вы хотите 2^32 символа, они должны быть длиной в среднем 4 байта. Если вы хотите, чтобы все ваши символы были размером 2 байта или меньше, то вы не можете иметь более 2^16 символов. UTF-8 дает разумный компромисс: все символы ASCII (ASCII от 0 до 127) имеют 1-байтовое представление, что отлично подходит для совместимости, но допускается гораздо больше символов.

Как и большинство кодировок переменной длины, включая виды escape-последовательностей, показанные выше, UTF-8 является мгновенным кодом. Это означает, что декодер просто читает байт за байтом и, как только он достигает последнего байта символа, он знает, что это за символ (и он знает, что это не начало более длинного символа).

Например, символ "А" представлен с использованием байта 65, и нет двух / трех / четырехбайтовых символов, чей первый байт равен 65. В противном случае декодер не сможет отличить эти символы от "А". "Затем следует что-то еще.

Но UTF-8 ограничен еще больше. Это гарантирует, что кодировка более короткого символа никогда не появится нигде в кодировке более длинного символа. Например, ни один из байтов в 4-байтовом символе не может быть 65.

Поскольку UTF-8 имеет 128 различных 1-байтовых символов (значения байтов 0-127), все 2, 3 и 4-байтовые символы должны состоять исключительно из байтов в диапазоне 128-256. Это большое ограничение. Тем не менее, он позволяет байтово-ориентированным строковым функциям работать практически без изменений. Например, С strstr() Функция всегда работает должным образом, если ее входные данные являются допустимыми строками UTF-8.

UTF-16

UTF-16 также является кодом переменной длины; его символы занимают 2 или 4 байта. 2-байтовые значения в диапазоне 0xD800-0xDFFF зарезервированы для построения 4-байтовых символов, а все 4-байтовые символы состоят из двух байтов в диапазоне 0xD800-0xDBFF, за которыми следуют 2 байта в диапазоне 0xDC00-0xDFFF. По этой причине Unicode не назначает никаких символов в диапазоне U+D800-U + DFFF.

UTF-32

UTF-32 - это код фиксированной длины, каждый символ длиной 4 байта. Хотя это позволяет кодировать 2^32 различных символов, в этой схеме разрешены только значения от 0 до 0x10FFFF.

Сравнение мощностей:

  • UTF-8: 2 097 152 (фактически 2 166 912, но из-за деталей дизайна некоторые из них соответствуют одному и тому же)
  • UTF-16: 1 112 064
  • UTF-32: 4 294 967 296 (но ограничены первыми 1 114 114)

Поэтому самым ограниченным является UTF-16! Формальное определение Unicode ограничило символы Unicode теми, которые можно кодировать с помощью UTF-16 (т. Е. Диапазон от U+0000 до U+10FFFF, исключая U+D800 до U+DFFF). UTF-8 и UTF-32 поддерживают все эти символы.

Система UTF-8 фактически "искусственно" ограничена 4 байтами. Его можно увеличить до 8 байт, не нарушая ограничений, которые я обрисовал ранее, и это даст емкость 2^42. Оригинальная спецификация UTF-8 фактически допускает до 6 байтов, что дает емкость 2^31. Но RFC 3629 ограничил его 4 байтами, так как именно столько нужно, чтобы покрыть все, что делает UTF-16.

Существуют и другие (в основном исторические) схемы кодирования Unicode, в частности UCS-2 (которая способна кодировать только от U+0000 до U+FFFF).

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

Что касается бонусного вопроса "Различаются ли эти кодировки количеством символов, которые они могут быть расширены для поддержки?" И да и нет. Способ кодирования UTF-8 и UTF-16 ограничивает общее число кодовых точек, которые они могут поддерживать, до менее чем 2^32. Однако Консорциум Unicode не будет добавлять кодовые точки к UTF-32, которые не могут быть представлены в UTF-8 или UTF-16. Это нарушит дух стандартов кодирования и сделает невозможным однозначное отображение с UTF-32 на UTF-8 (или UTF-16).

Я лично всегда проверяю пост Джоэла о юникоде, кодировках и наборах символов, когда сомневаешься.

Все кодировки UTF-8/16/32 могут отображать все символы Unicode. См . Сравнение кодировок Unicode в Википедии.

Эта статья IBM Кодирование ваших XML-документов в UTF-8 очень полезна и указывает, что если у вас есть выбор, лучше выбрать UTF-8. Главным образом причины - широкая поддержка инструментов, и UTF-8 обычно может проходить через системы, которые не знают о юникоде.

Из раздела Что говорят спецификации в статье IBM:

И W3C, и IETF в последнее время стали более непреклонны в выборе UTF-8 первым, последним, а иногда и единственным. Символьная модель W3C для World Wide Web 1.0: Основные положения гласят: "Когда требуется уникальная кодировка символов, кодировка символов ДОЛЖНА быть UTF-8, UTF-16 или UTF-32. US-ASCII совместима сверху с UTF-8 (строка US-ASCII также является строкой UTF-8, см. [RFC 3629]), и поэтому UTF-8 подходит, если требуется совместимость с US-ASCII ". На практике совместимость с US-ASCII настолько полезна, что почти обязательна. W3C мудро объясняет: "В других ситуациях, таких как API, UTF-16 или UTF-32 могут быть более подходящими. Возможные причины выбора одного из них включают в себя эффективность внутренней обработки и совместимость с другими процессами".

Как все говорили, UTF-8, UTF-16 и UTF-32 могут кодировать все кодовые точки Unicode. Однако вариант UCS-2 (иногда ошибочно называемый UCS-16) не может, и именно этот вы можете найти, например, в Windows XP / Vista.

Смотрите Википедию для получения дополнительной информации.

Редактировать: я не прав насчет Windows, NT был единственным, кто поддерживает UCS-2. Тем не менее, многие приложения Windows будут использовать одно слово на кодовую точку, как в UCS-2, так что вы, вероятно, найдете ошибки. Смотрите еще одну статью в Википедии. (Спасибо ДжейсонТру)

Другие вопросы по тегам