UTF-8, UTF-16 и UTF-32


487

Каковы различия между UTF-8, UTF-16 и UTF-32?

Я понимаю, что все они будут хранить Unicode, и что каждый использует различное количество байтов для представления символа. Есть ли преимущество выбора одного над другим?


36
Посмотрите это видео, если вам интересно, как работает Unicode youtube.com/watch?v=MijmeoH9LT4

1
Видео посвящено UTF-8, и да, оно хорошо объясняет, как работает кодирование переменной длины, и в основном совместимо с компьютерами, которые читают или пишут только ASCII фиксированной длины. Unicode ребята были умны при разработке кодировки UTF-8.
мин

1
Я создал онлайн-инструмент для конвертации и сравнения.
Амит Кумар Гупта

1
UTF-8 является стандартом де-факто в большинстве современных программ для сохраненных файлов . В частности, это наиболее широко используемая кодировка для HTML и файлов конфигурации и перевода (например, Minecraft не принимает никакую другую кодировку для всей своей текстовой информации). UTF-32 быстр для представления внутренней памяти , а UTF-16 устарел , в настоящее время используется только в Win32 по историческим причинам ( UTF-16 был фиксированной длины, когда была Windows 95)
Kotauskas

@VladislavToncharov UTF-16 никогда не был кодированием фиксированной длины. Вы путаете это с UCS-2.

Ответы:


373

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

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

UTF-32 будет охватывать все возможные символы в 4 байта. Это делает его довольно раздутым. Я не могу думать ни о каком преимуществе использования этого.


165
Преимущество UTF-32: вам не нужно декодировать сохраненные данные в 32-битную кодовую точку Unicode, например, для обработки символов. Кодовая точка уже доступна прямо в вашем массиве / векторе / строке.
Рич

22
Также легче разобрать, если (небеса тебе помогают) нужно заново внедрить колесо.
Пол Макмиллан

24
Ну, UTF-8 имеет преимущество в сетевых передачах - не нужно беспокоиться о порядке байтов, поскольку вы передаете данные по одному байту за раз (в отличие от 4).
Тим Час

30
@richq Вы не можете выполнять посимвольную обработку в UTF-32, так как кодовая точка не всегда соответствует символу.
Хомякен

4
Преимущество UTF-32: манипулирование строками возможно быстрее по сравнению с эквивалентом UTF-8
Уэс

332

Короче говоря:

  • UTF-8: кодирование с переменной шириной, обратно совместимое с ASCII. Символы ASCII (от U + 0000 до U + 007F) занимают 1 байт, кодовые точки от U + 0080 до U + 07FF занимают 2 байта, кодовые точки от U + 0800 до U + FFFF занимают 3 байта, кодовые точки от U + 10000 до U + 10FFFF взять 4 байта. Хорошо для английского текста, не так хорошо для азиатского текста.
  • UTF-16: кодирование переменной ширины. Кодовые точки от U + 0000 до U + FFFF занимают 2 байта, кодовые точки от U + 10000 до U + 10FFFF занимают 4 байта. Плохо для английского текста, хорошо для азиатского текста.
  • UTF-32: кодирование с фиксированной шириной. Все кодовые точки занимают четыре байта. Огромная память, но быстро работать. Редко используемый.

Длинно: смотрите Википедию: UTF-8 , UTF-16 и UTF-32 .


65
@spurrymoses: я имею в виду строго объем пространства, занимаемого байтами данных. UTF-8 требует 3 байта на азиатский символ, в то время как UTF-16 требует только 2 байта на азиатский символ. Это на самом деле не является серьезной проблемой, так как в наши дни компьютеры имеют тонны памяти по сравнению со средним объемом текста, хранящегося в памяти программы.
Адам Розенфилд

12
UTF-32 больше редко используется ... в OSX и Linux по wchar_tумолчанию используется 4 байта. У gcc есть опция, -fshort-wcharкоторая уменьшает размер до 2 байтов, но нарушает двоичную совместимость с библиотеками std.
Вино

9
@PandaWood ofcource UTF-8 может кодировать любой символ! Но сравнивали ли вы требования к памяти с UTF-16? Кажется, вы упускаете суть!
Устаман Сангат

16
Если бы кто-то сказал, что UTF-8 «не очень хорош для азиатского текста» в контексте всех форматов кодирования, включая те, которые не могут кодировать Unicode, они, конечно, были бы неправы. Но это не контекст. Контекст требований к памяти исходит из того факта, что вопрос (и ответ) сравнивает UTF-8, UTF-16 и UTF-32, которые будут кодировать азиатский текст, но использовать разные объемы памяти / памяти. Отсюда следует, что их относительное совершенство, естественно, полностью зависит от требований к памяти. «Не так хорошо»! = «Не хорошо».
Пол Грегори

5
@MCGafter: Ну, конечно, есть. Если вы хотите доверия, идите прямо к рту лошади в Консорциуме Юникод . См. Главу 2.5 для описания кодировок UTF- *. Но для получения простого понимания кодировок на высоком уровне я обнаружил, что статьи в Википедии являются гораздо более доступным источником.
Адам Розенфилд

116
  • UTF-8 - это переменные от 1 до 4 байтов.

  • UTF-16 является переменной 2 или 4 байта.

  • UTF-32 фиксируется 4 байта.

Примечание: UTF-8 может занимать от 1 до 6 байт с последним соглашением: https://lists.gnu.org/archive/html/help-flex/2005-01/msg00030.html


35
UTF8 на самом деле составляет от 1 до 6 байтов.
Urkle

6
@Urkle технически корректен, потому что отображение полного диапазона UTF32 / LE / BE включает в себя U-00200000 - U-7FFFFFFF, даже если Unicode v6.3 заканчивается на U-0010FFFF включительно. Вот хороший пример того, как кодировать / дек 5 и 6 байтов utf8: lists.gnu.org/archive/html/help-flex/2005-01/msg00030.html

4
подкрепляя их соответствующими ссылочными частями и их источниками?
n611x007

20
@Urkle Нет, UTF-8 не может быть 5 или 6 байтов. Кодовые точки Unicode ограничены 21 битом, что ограничивает UTF-8 до 4 байтов. (Конечно, вы можете расширить принцип UTF-8 для кодирования произвольных больших целых чисел, но это не будет Unicode.) См. RFC 3629.
rdb

11
Цитата из Википедии: В ноябре 2003 года RFC 3629 ограничил UTF-8, чтобы он соответствовал ограничениям кодировки символов UTF-16: явный запрет кодовых точек, соответствующих старшим и младшим суррогатным символам, удалил более 3% трехбайтовых последовательностей. и заканчивая U + 10FFFF, удалили более 48% четырехбайтовых последовательностей и все пяти- и шестибайтовые последовательности.
Адам Кальвет Бол

79

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

Вкратце, UTF-32 использует 32-битные значения для каждого символа. Это позволяет им использовать код фиксированной ширины для каждого символа.

UTF-16 использует 16-битный по умолчанию, но это дает только 65 тыс. Возможных символов, что далеко не достаточно для полного набора Unicode. Поэтому некоторые символы используют пары 16-битных значений.

И UTF-8 использует 8-битные значения по умолчанию, что означает, что 127 первых значений являются однобайтовыми символами фиксированной ширины (старший бит используется для обозначения того, что это начало многобайтовой последовательности, оставляя 7 биты для фактического значения символа). Все остальные символы кодируются как последовательности длиной до 4 байтов (если память служит).

И это приводит нас к преимуществам. Любой символ ASCII напрямую совместим с UTF-8, поэтому для обновления устаревших приложений UTF-8 является распространенным и очевидным выбором. Почти во всех случаях он также использует наименьшее количество памяти. С другой стороны, вы не можете дать никаких гарантий относительно ширины символа. Он может иметь ширину 1, 2, 3 или 4 символа, что затрудняет манипулирование строками.

UTF-32 противоположен, он использует большую часть памяти (каждый символ имеет фиксированную ширину 4 байта), но с другой стороны, вы знаете, что каждый символ имеет такую ​​точную длину, поэтому манипулирование строками становится намного проще. Вы можете вычислить количество символов в строке просто по длине в байтах строки. Вы не можете сделать это с UTF-8.

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

Наконец, часто бывает полезно просто ознакомиться с тем, что поддерживает платформа. Windows использует UTF-16 для внутреннего использования, поэтому для Windows это очевидный выбор.

Linux немного отличается, но они обычно используют UTF-8 для всего, что соответствует Unicode.

Итак, короткий ответ: все три кодировки могут кодировать один и тот же набор символов, но они представляют каждый символ как разные последовательности байтов.


12
Неверно говорить, что Unicode назначает уникальное целое число каждому графическому символу . Он присваивает это каждой кодовой точке, но некоторые кодовые точки являются невидимыми управляющими символами , а некоторые графические символы требуют представления нескольких кодовых точек .
2012 года

15
@tchrist: да, неточно. Проблема в том, что для точного объяснения Unicode вам нужно написать тысячи страниц. Я надеялся объяснить основную концепцию, чтобы объяснить разницу между кодировками
jalf

@jalf lol, так что в основном, чтобы объяснить Unicode, вам нужно написать спецификацию ядра Unicode
Джастин Омс

@tchrist Более конкретно, вы можете создавать китайские символы из предоставленных примитивов (но они находятся в одной и той же диаграмме, так что вы просто будете использовать нереальный объем пространства - либо диск, либо ОЗУ - для их кодирования) вместо использования встроенные.
Котаускас

44

Unicode - это стандарт, и о UTF-x можно думать как о технической реализации для некоторых практических целей:

  • UTF-8 - « оптимизированный по размеру »: лучше всего подходит для данных на основе латинских символов (или ASCII), занимает всего 1 байт на символ, но размер увеличивается соответственно разнообразию символов (и в худшем случае может увеличиваться до 6 байтов на символ)
  • UTF-16 - « баланс »: требуется минимум 2 байта на символ, что достаточно для существующего набора основных языков с фиксированным размером для упрощения обработки символов (но размер все еще является переменным и может увеличиваться до 4 байтов на символ )
  • UTF-32 - « производительность »: позволяет использовать простые алгоритмы как результат символов фиксированного размера (4 байта), но с недостатком памяти

«Основные языки» не так
широко

2
UTF-16 на самом деле оптимизирован по размеру для не ASCII-символов. Ведь это действительно зависит от того, с какими языками он будет использоваться.
Tuxayo

@tuxayo полностью согласен, стоит отметить наборы символов Ханзи и Кандзи для азиатской части мира.
ладья

Должен быть главный ответ. Это слишком правильно, чтобы быть похороненным здесь.
Михал Штейн

28

Я попытался дать простое объяснение в моем блоге .

UTF-32

требуется 32 бита (4 байта) для кодирования любого символа. Например, чтобы представить кодовую точку символа «A» с помощью этой схемы, вам нужно написать 65 в 32-битном двоичном числе:

00000000 00000000 00000000 01000001 (Big Endian)

Если вы посмотрите поближе, вы заметите, что при использовании схемы ASCII самые правые семь битов - это на самом деле те же биты. Но поскольку UTF-32 является схемой фиксированной ширины , мы должны добавить три дополнительных байта. Это означает, что если у нас есть два файла, которые содержат только символ «A», один кодируется в кодировке ASCII, а другой - в кодировке UTF-32, их размер будет 1 байт и 4 байта соответственно.

UTF-16

Многие думают, что, поскольку UTF-32 использует фиксированную ширину 32 бита для представления кодовой точки, UTF-16 имеет фиксированную ширину 16 бит. НЕПРАВИЛЬНО!

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

Поскольку для представления символа «A» достаточно 7 битов, теперь мы можем использовать 2 байта вместо 4, как UTF-32. Это будет выглядеть так:

00000000 01000001

UTF-8,

Вы правильно догадались. В UTF-8 кодовая точка может быть представлена ​​с использованием 32, 16, 24 или 8 битов, а в качестве системы UTF-16 эта также является системой кодирования переменной длины.

Наконец, мы можем представить «A» так же, как мы представляем его, используя систему кодирования ASCII:

01001101

Небольшой пример, где UTF-16 на самом деле лучше, чем UTF-8:

Рассмотрим китайскую букву «語» - ее кодировка UTF-8:

11101000 10101010 10011110

Хотя его кодировка UTF-16 короче:

10001010 10011110

Чтобы понять представление и то, как оно интерпретируется, посетите исходный пост.


19

UTF-8,

  • не имеет понятия порядка байтов
  • использует от 1 до 4 байтов на символ
  • ASCII является совместимым подмножеством кодирования
  • полностью самосинхронизирующийся, например, отброшенный байт из любого места в потоке будет повреждать не более одного символа
  • почти все европейские языки кодируются в два байта или меньше на символ

UTF-16

  • должен быть проанализирован с известным порядком байтов или чтением метки порядка байтов (BOM)
  • использует 2 или 4 байта на символ

UTF-32

  • каждый символ 4 байта
  • должен быть проанализирован с известным порядком байтов или чтением метки порядка байтов (BOM)

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

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


Как работает «самосинхронизация» в UTF-8? Можете ли вы привести примеры для 1-байтовых и 2-байтовых символов?
Корай Тугай

2
@KorayTugay Допустимые короткие байтовые строки никогда не используются в более длинных символах. Например, ASCII находится в диапазоне 0-127, что означает, что все однобайтовые символы имеют форму 0xxxxxxxв двоичном виде . Все двухбайтовые символы начинаются со 110xxxxxвторого байта 10xxxxxx. Допустим, первый символ двухбайтового символа потерян. Как только вы видите 10xxxxxxбез предшествующего 110xxxxxx, вы можете точно определить, был ли потерян или поврежден байт, и отбросить этот символ (или повторно запросить его с сервера или чего-либо еще), и двигаться дальше, пока вы снова не увидите действительный первый байт. ,
Крис

1
если у вас есть смещение к символу, у вас есть смещение к этому символу - utf8, utf16 или utf32 будут работать точно так же; т.е. все они одинаково хороши при произвольном доступе по смещению символов в байтовый массив. Идея, что utf32 лучше подсчитывает символы, чем utf8, также полностью ложна. Элемент кода (который является не то же самое, что опять - таки характер, это не то же самое , как графемы .. вздыхаю), составляет 32 бита в UTF32 и от 8 до 32 битов в utf8, но персонаж может охватывать несколько кодовых, которые уничтожает главное преимущество, которое люди утверждают, что utf32 имеет над utf8.
Яснее

14

Я провел несколько тестов для сравнения производительности базы данных между UTF-8 и UTF-16 в MySQL.

Обновить скорости

UTF-8,

Введите описание изображения здесь

UTF-16

Введите описание изображения здесь

Вставить скорость

Введите описание изображения здесь

Введите описание изображения здесь

Удалить скорость

Введите описание изображения здесь

Введите описание изображения здесь


14

В UTF-32 все символы кодируются 32-битными символами. Преимущество в том, что вы можете легко рассчитать длину строки. Недостатком является то, что для каждого символа ASCII вы тратите лишние три байта.

В UTF-8 символы имеют переменную длину, символы ASCII кодируются одним байтом (восемь битов), большинство западных специальных символов кодируются либо двумя байтами, либо тремя байтами (например, € составляет три байта), и более экзотические символы могут занимать до четырех байтов. Очевидным недостатком является то, что априори вы не можете рассчитать длину строки. Но для кодирования латинского (английского) алфавитного текста требуется намного меньше байтов, чем для UTF-32.

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

Очевидно, что из этих трех наиболее распространенным является UTF-8.


Зачем мне рассчитывать длину строки при разработке сайтов? Есть ли преимущество выбора UTF-8 / UTF-16 в веб-разработке?
Морфидон

«Преимущество состоит в том, что вы можете легко вычислить длину строки». Если вы определяете длину числом # кодовых точек, тогда да, вы можете просто разделить длину байта на 4, чтобы получить ее с помощью UTF-32. Однако это не очень полезное определение: оно может не относиться к количеству символов. Кроме того, нормализация может изменить количество кодовых точек в строке. Например, французское слово «été» может быть закодировано как минимум 4 различными способами с 3 разными длинами кодовой точки.

UTF-16, возможно, быстрее, чем UTF-8, и при этом не тратит впустую память, как UTF-32.
Михал Штейн

6

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

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


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

2

Как уже упоминалось, разница в основном заключается в размере основных переменных, которые в каждом случае увеличиваются, чтобы можно было представить больше символов.

Тем не менее, шрифты, кодирование и все остальное очень сложно (излишне?), Поэтому для более подробной информации необходима большая ссылка:

http://www.cs.tut.fi/~jkorpela/chars.html#ascii

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

Павел.


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

-2

Короче говоря, единственная причина использования UTF-16 или UTF-32 заключается в поддержке неанглийских и древних скриптов соответственно.

Мне было интересно, почему кто-то выбрал кодировку не-UTF-8, когда она, очевидно, более эффективна для веб / программирования.

Распространенное заблуждение - число с суффиксом НЕ является показателем его возможностей. Все они поддерживают полный Unicode, только то, что UTF-8 может обрабатывать ASCII с одним байтом, поэтому он более эффективен / менее подвержен повреждению ЦП и через Интернет.

Немного хорошего чтения: http://www.personal.psu.edu/ejp10/blogs/gotunicode/2007/10/which_utf_do_i_use.html и http://utf8everywhere.org


Я не уверен, почему вы предлагаете, чтобы использование UTF-16 или UTF-32 поддерживало неанглийский текст. UTF-8 справится с этим просто отлично. И в английском тексте есть символы не ASCII. Как не присоединяющийся к нулевой ширине. Или их тире. Боюсь, этот ответ не имеет большого значения.
IInspectable

Этот вопрос подвержен отрицательному голосованию, поскольку UTF-8 по-прежнему широко используется в файлах HTML, даже если большинство символов являются 3-байтовыми символами в UTF-8,
Ṃųỻịgǻňạcểơửṩ

@ Инспектируемая поддержка - не лучшая формулировка, продвижение или лучшая поддержка будет более точной
robotik

Отправка страницы типа utf8everywhere.org - это не то, что я сделал бы в SO-ответе.
Михал Штейн
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.