Зачем нам нужен Юникод?
В (не слишком) первые дни все, что существовало, было ASCII. Это было хорошо, так как все, что когда-либо понадобилось, это несколько контрольных символов, знаки препинания, цифры и буквы, подобные тем, которые указаны в этом предложении. К сожалению, сегодняшний странный мир глобального общения и социальных сетей не предвиделся, и нередко видеть английский, английский, английский, английский и французский в том же документе (надеюсь, я не сломал старые браузеры).
Но ради аргумента, допустим, Джо Средний разработчик программного обеспечения. Он настаивает на том, что ему когда-либо понадобится только английский, и поэтому он хочет использовать только ASCII. Это может быть хорошо для пользователя Джо , но это не хорошо для разработчика программного обеспечения Джо . Приблизительно половина мира использует нелатинские символы, и использование ASCII для этих людей, возможно, неуместно, и, кроме того, он закрывает свое программное обеспечение для большой и растущей экономики.
Поэтому необходим всеобъемлющий набор символов, включающий все языки. Так появился Unicode. Каждому символу присваивается уникальный номер, называемый кодовой точкой . Одно из преимуществ 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 представление UTF-16 является просто его кодовой точкой. Однако для не-BMP символов UTF-16 вводит суррогатные пары . В этом случае комбинация двух двухбайтовых частей отображается на не-BMP символ. Эти двухбайтовые части взяты из числового диапазона BMP, но гарантируются стандартом Unicode как недопустимые символы BMP. Кроме того, поскольку UTF-16 имеет два байта в качестве базовой единицы, на него влияет порядок байтов . Чтобы компенсировать это, зарезервированная метка порядка байтов может быть размещена в начале потока данных, который указывает порядковый номер. Таким образом, если вы читаете ввод 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 (комбинированная тильда) образуют -, но кодовая точка U + 00F1 образует -. Они должны выглядеть одинаково, но простой алгоритм подсчета вернет 2 для первого примера, 1 для последнего. Это не обязательно неправильно, но может и не быть желаемым результатом.
Сравнение на равенство: A, А и Α выглядят одинаково, но они латинские, кириллические и греческие соответственно. У вас также есть такие случаи, как C и Ⅽ, один - буква, другой - римская цифра. Кроме того, у нас есть комбинации символов, которые необходимо учитывать. Для получения дополнительной информации см. Повторяющиеся символы в Юникоде .
Суррогатные пары: они встречаются достаточно часто на SO, поэтому я просто приведу несколько примеров ссылок:
Другие ?: