Каковы различия между UTF-8, UTF-16 и UTF-32?
Я понимаю, что все они будут хранить Unicode, и что каждый использует различное количество байтов для представления символа. Есть ли преимущество выбора одного над другим?
Каковы различия между UTF-8, UTF-16 и UTF-32?
Я понимаю, что все они будут хранить Unicode, и что каждый использует различное количество байтов для представления символа. Есть ли преимущество выбора одного над другим?
Ответы:
UTF-8 имеет преимущество в случае, когда символы ASCII представляют большинство символов в блоке текста, потому что UTF-8 кодирует их в 8 бит (как ASCII). Также полезно то, что файл UTF-8, содержащий только символы ASCII, имеет ту же кодировку, что и файл ASCII.
UTF-16 лучше, когда ASCII не является преобладающим, так как он использует в основном 2 байта на символ. UTF-8 начнет использовать 3 или более байтов для символов высшего порядка, где UTF-16 для большинства символов остается всего 2 байта.
UTF-32 будет охватывать все возможные символы в 4 байта. Это делает его довольно раздутым. Я не могу думать ни о каком преимуществе использования этого.
Короче говоря:
wchar_t
умолчанию используется 4 байта. У gcc есть опция, -fshort-wchar
которая уменьшает размер до 2 байтов, но нарушает двоичную совместимость с библиотеками std.
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
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.
Итак, короткий ответ: все три кодировки могут кодировать один и тот же набор символов, но они представляют каждый символ как разные последовательности байтов.
Unicode - это стандарт, и о UTF-x можно думать как о технической реализации для некоторых практических целей:
Я попытался дать простое объяснение в моем блоге .
требуется 32 бита (4 байта) для кодирования любого символа. Например, чтобы представить кодовую точку символа «A» с помощью этой схемы, вам нужно написать 65 в 32-битном двоичном числе:
00000000 00000000 00000000 01000001 (Big Endian)
Если вы посмотрите поближе, вы заметите, что при использовании схемы ASCII самые правые семь битов - это на самом деле те же биты. Но поскольку UTF-32 является схемой фиксированной ширины , мы должны добавить три дополнительных байта. Это означает, что если у нас есть два файла, которые содержат только символ «A», один кодируется в кодировке ASCII, а другой - в кодировке UTF-32, их размер будет 1 байт и 4 байта соответственно.
Многие думают, что, поскольку 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 кодовая точка может быть представлена с использованием 32, 16, 24 или 8 битов, а в качестве системы UTF-16 эта также является системой кодирования переменной длины.
Наконец, мы можем представить «A» так же, как мы представляем его, используя систему кодирования ASCII:
01001101
Рассмотрим китайскую букву «語» - ее кодировка UTF-8:
11101000 10101010 10011110
Хотя его кодировка UTF-16 короче:
10001010 10011110
Чтобы понять представление и то, как оно интерпретируется, посетите исходный пост.
UTF-8 будет наиболее экономичным, если большинство символов не из пространства символов CJK (китайский, японский и корейский).
UTF-32 лучше всего подходит для произвольного доступа по смещению символов в байтовый массив.
0xxxxxxx
в двоичном виде . Все двухбайтовые символы начинаются со 110xxxxx
второго байта 10xxxxxx
. Допустим, первый символ двухбайтового символа потерян. Как только вы видите 10xxxxxx
без предшествующего 110xxxxxx
, вы можете точно определить, был ли потерян или поврежден байт, и отбросить этот символ (или повторно запросить его с сервера или чего-либо еще), и двигаться дальше, пока вы снова не увидите действительный первый байт. ,
Я провел несколько тестов для сравнения производительности базы данных между UTF-8 и UTF-16 в MySQL.
В UTF-32 все символы кодируются 32-битными символами. Преимущество в том, что вы можете легко рассчитать длину строки. Недостатком является то, что для каждого символа ASCII вы тратите лишние три байта.
В UTF-8 символы имеют переменную длину, символы ASCII кодируются одним байтом (восемь битов), большинство западных специальных символов кодируются либо двумя байтами, либо тремя байтами (например, € составляет три байта), и более экзотические символы могут занимать до четырех байтов. Очевидным недостатком является то, что априори вы не можете рассчитать длину строки. Но для кодирования латинского (английского) алфавитного текста требуется намного меньше байтов, чем для UTF-32.
UTF-16 также переменной длины. Символы кодируются либо двумя байтами, либо четырьмя байтами. Я действительно не вижу смысла. Недостатком является то, что он имеет переменную длину, но он не имеет такого преимущества, как экономия места, такого как UTF-8.
Очевидно, что из этих трех наиболее распространенным является UTF-8.
В зависимости от среды разработки у вас может даже не быть выбора, какую кодировку использовать для строкового типа данных.
Но для хранения и обмена данными я бы всегда использовал UTF-8, если у вас есть выбор. Если у вас есть в основном ASCII-данные, это даст вам наименьшее количество данных для передачи, но при этом вы сможете все закодировать. Оптимизация для наименьшего количества операций ввода-вывода - это путь для современных машин.
Как уже упоминалось, разница в основном заключается в размере основных переменных, которые в каждом случае увеличиваются, чтобы можно было представить больше символов.
Тем не менее, шрифты, кодирование и все остальное очень сложно (излишне?), Поэтому для более подробной информации необходима большая ссылка:
http://www.cs.tut.fi/~jkorpela/chars.html#ascii
Не ожидайте, что вы все это поймете, но если вы не хотите, чтобы у вас возникали проблемы позже, стоит изучить как можно больше, как можно раньше (или просто попросить кого-то другого разобраться в этом за вас).
Павел.
Короче говоря, единственная причина использования 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