Зачем нам нужен Юникод?
В (не слишком) первые годы все, что существовало, было ASCII. Это было хорошо, так как все, что когда-либо понадобилось, это несколько контрольных символов, знаки препинания, цифры и буквы, подобные тем, которые указаны в этом предложении. К сожалению, сегодняшний странный мир глобального общения и социальных сетей не предвиделся, и нередко видеть английский, английский, английский, английский и французский в том же документе (надеюсь, я не сломал старые браузеры).
Но, ради аргумента, допустим, Джо Средний разработчик программного обеспечения. Он настаивает на том, что ему когда-либо понадобится только английский, и поэтому он хочет использовать только ASCII. Это может быть хорошо для Джо пользователя , но это не хорошо для Джо разработчика программного обеспечения . Приблизительно половина мира использует нелатинские символы, и использование ASCII для этих людей, возможно, неуместно, и, кроме того, он закрывает свое программное обеспечение для большой и растущей экономики.
Следовательно, необходим всеобъемлющий набор символов, включающий все языки. Так появился Юникод. Каждому символу присваивается уникальный номер, называемый кодовая точка . Одно из преимуществ Unicode над другими возможными наборами состоит в том, что первые 256 кодовых точек идентичны ISO-8859-1 , а следовательно, и ASCII. Кроме того, подавляющее большинство обычно используемых символов представляются только двумя байтами в области, называемой Базовая многоязычная плоскость (BMP) . Теперь для доступа к этому набору символов требуется кодировка символов, и, как задается вопрос, я сосредоточусь на UTF-8 и UTF-16.
Особенности памяти
Так сколько байт дают доступ к каким символам в этих кодировках?
- UTF-8
- 1 байт: стандарт ASCII
- 2 байта: арабский, иврит, большинство европейских шрифтов (особенно исключая грузинский )
- 3 байта: BMP
- 4 байта: все символы Unicode
- UTF-16:
- 2 байта: BMP
- 4 байта: все символы Unicode
Стоит отметить, что в число символов, не входящих в BMP, входят древние сценарии, математические символы, музыкальные символы и более редкие китайские / японские / корейские (CJK) символы.
Если вы будете работать в основном с символами ASCII, то UTF-8, безусловно, более эффективно использует память. Однако, если вы работаете в основном с неевропейскими сценариями, использование UTF-8 может потреблять до 1,5 раз меньше памяти, чем UTF-16. При работе с большими объемами текста, например большими веб-страницами или документами с длинными словами, это может повлиять на производительность.
Основы кодирования
Примечание. Если вы знаете, как кодируются UTF-8 и UTF-16, перейдите к следующему разделу для практического применения.
- UTF-8: Для стандартных символов ASCII (0-127) коды UTF-8 идентичны. Это делает UTF-8 идеальным, если требуется обратная совместимость с существующим текстом ASCII. Другие символы требуют от 2-4 байтов. Это делается путем резервирования некоторых битов в каждом из этих байтов, чтобы указать, что он является частью многобайтового символа. В частности, первый бит каждого байта равен
1
, чтобы избежать конфликта с символами ASCII.
- UTF-16: Для действительной BMP-чарыCTS, представление UTF-16 является просто его кодовой точкой. Однако для символов, отличных от BMP, UTF-16 вводит суррогатных пар . В этом случае комбинация двух двухбайтовых частей отображается на не-BMP символ. Эти двухбайтовые части взяты из числового диапазона BMP, но в соответствии со стандартом Unicode гарантированно недопустимы в качестве символов BMP. Кроме того, поскольку UTF-16 имеет два байта в качестве базовой единицы, на него влияет endianness . Чтобы компенсировать это, зарезервированная метка порядка байтов может быть размещена в начале потока данных, который указывает порядковый номер. Таким образом, если вы читаете ввод UTF-16, и не указан порядковый номер, вы должны проверить это.
Как видно, UTF-8 и UTF-16 далеко не совместимы друг с другом. Поэтому, если вы делаете ввод / вывод, убедитесь, что вы знаете, какую кодировку вы используете! Более подробную информацию об этих кодировках см. В UTF FAQ .
Практические вопросы программирования
Типы символьных и строковых данных: Как они кодируются на языке программирования? Если они являются необработанными байтами, в ту минуту, когда вы попытаетесь вывести символы, отличные от ASCII, у вас могут возникнуть несколько проблем. Кроме того, даже если тип символа основан на UTF, это не означает, что строки являются правильными UTF. Они могут разрешать байтовые последовательности, которые являются недопустимыми. Как правило, вам придется использовать библиотеку, которая поддерживает UTF, например ICU для C, C ++ и Java. В любом случае, если вы хотите ввести / вывести что-то, отличное от кодировки по умолчанию, вам придется сначала преобразовать это.
Рекомендуемые / стандартные / доминантные кодировки: Когда предоставляется выбор, какой из UTF использовать, обычно лучше следовать рекомендуемым стандартам для среды, в которой вы работаете. Например, UTF-8 является доминирующим в Интернете, и начиная с HTML5, это была рекомендуемая кодировка . И наоборот, среды .NET и Java основаны на символьном типе UTF-16. Смущает (и неправильно), ссылки часто делаются на «кодировку Unicode», которая обычно ссылается на доминирующее кодирование UTF в данной среде.
Поддержка библиотек: Какие кодировки поддерживают библиотеки, которые вы используете? Они поддерживают угловые дела? Поскольку необходимость является матерью изобретения, библиотеки UTF-8, как правило, будут правильно поддерживать 4-байтовые символы, поскольку часто встречаются 1, 2 и даже 3 байта. Однако не все предполагаемые библиотеки UTF-16 поддерживают суррогатные пары должным образом, поскольку они встречаются очень редко.
Подсчет символов: Существует комбинаций символов в Юникоде. Например, кодовая точка U + 006E (n) и U + 0303 (комбинированная тильда) образуют n & # x303 ;, но кодовая точка U + 00F1 формирует & # xF1; Они должны выглядеть одинаково, но простой алгоритм подсчета вернет 2 для первого примера, 1 для последнего. Это не обязательно неправильно, но может и не быть желаемым результатом.
Сравнение на равенство: & # x41 ;, & # x410; и & # x391; выглядят одинаково, но они латинские, кириллические и греческие соответственно. У вас также есть такие случаи, как & # x43; и & # x216D ;, одна - буква, другая - римская цифра. Кроме того, у нас есть комбинации символов, которые необходимо учитывать. Для получения дополнительной информации см. Повторяющиеся символы в Unicode .
Суррогатные пары: Они появляются достаточно часто на SO, поэтому я просто приведу несколько примеров ссылок:
Другие: