Что такое Юникод, UTF-8, UTF-16? - PullRequest
345 голосов
/ 11 февраля 2010

Что является основой для Unicode и зачем нужен UTF-8 или UTF-16? Я исследовал это в Google и искал здесь, но мне это не понятно.

В VSS при сравнении файлов иногда появляется сообщение о том, что два файла имеют разные UTF. Почему это так?

Пожалуйста, объясните простыми словами.

Ответы [ 9 ]

491 голосов
/ 28 февраля 2013

Зачем нам нужен Юникод?

В (не слишком) первые годы все, что существовало, было 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, поэтому я просто приведу несколько примеров ссылок:

Другие:

57 голосов
/ 06 января 2015
  • Unicode
    • - это набор символов, используемых по всему миру
  • UTF-8
    • кодировка символов, способная кодировать все возможные символы (называемые кодовыми точками) в Unicode.
    • кодовая единица - 8 бит
    • использовать от одного до четырех единиц кода для кодирования Unicode
    • 00100100 для " $ " (один 8-разрядный); 11000010 10100010 для " ¢ " (два 8-разрядных) ); 11100010 10000010 10101100 для "" (три 8-битных)
  • UTF-16
    • другая кодировка символов
    • кодовая единица составляет 16 бит
    • использовать одну или две единицы кода для кодирования Unicode
    • 00000000 00100100 для " $ " (один 16 бит); 11011000 01010010 11011111 01100010 для " ? " (два 16-бит)
26 голосов
/ 27 октября 2015

Юникод - довольно сложный стандарт. Не бойся слишком, но будь готов к работе! [2]

Поскольку заслуживающий доверия ресурс всегда необходим, но официальный отчет огромен, я предлагаю прочитать следующее:

  1. Абсолютный минимум Каждый разработчик программного обеспечения Абсолютно, положительно должен знать о Юникоде и наборах символов (без извинений!) Введение Джоэла Спольски, генерального директора Stack Exchange.
  2. Для BMP и за ее пределами! Учебное пособие Эрика Мюллера, технического директора, а затем вице-президента консорциума Unicode. (первые 20 слайдов и все готово)

Краткое объяснение:

Компьютеры читают байты, а люди читают символы, поэтому мы используем стандарты кодирования для сопоставления символов с байтами. ASCII был первым широко используемым стандартом, но охватывает только латиницу (7 бит / символ может представлять 128 различных символов). Юникод - это стандарт, цель которого - охватить все возможные символы в мире (может содержать до 1114 112 символов, то есть максимум 21 бит / символ. В настоящее время Unicode 8.0 определяет 120 737 символов, и все).

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

Каждый символ занимает нумерованную позицию от 0 до 1 114 111 (шестнадцатеричное: 0-10FFFF), называемое кодовая точка .
Форма кодирования отображает кодовую точку в последовательность кодовых единиц. кодовая единица - это способ организации символов в памяти, 8-битных, 16-битных блоков и т. Д. UTF-8 использует от 1 до 4 блоков по 8 битов, а UTF-16 использует 1 или 2 блока по 16 битов, чтобы охватить весь Unicode максимум из 21 бита. Единицы используют префиксы, чтобы можно было определить границы символов, и чем больше единиц, тем больше префиксов занимают биты. Таким образом, хотя UTF-8 использует 1 байт для латинского алфавита, ему требуется 3 байта для более поздних сценариев внутри базовой многоязычной плоскости, в то время как UTF-16 использует 2 байта для всех этих. И это их главное отличие.
Наконец, схема кодирования (например, UTF-16BE или UTF-16LE) отображает (сериализует) последовательность кодовых единиц в последовательность байтов.

символ: π
кодовая точка: U + 03C0
формы кодирования (кодовые единицы):
UTF-8: CF 80
UTF-16: 03C0
схемы кодирования (байты):
UTF-8: CF 80
UTF-16BE: 03 C0
UTF-16LE: C0 03

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

18 голосов
/ 05 июля 2010

Изначально Unicode должен был иметь 16-битное кодирование фиксированной ширины (UCS-2). Первые пользователи Unicode, такие как Java и Windows NT, построили свои библиотеки на 16-битных строках.

Позже область действия Unicode была расширена и теперь включает в себя исторические символы, для чего потребуется более 65 536 кодов, которые будет поддерживать 16-битное кодирование. Чтобы допустить представление дополнительных символов на платформах, которые использовали UCS-2, была введена кодировка UTF-16. Он использует «суррогатные пары» для представления символов в дополнительных плоскостях.

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

12 голосов
/ 18 января 2017

Эта статья объясняет все детали http://kunststube.net/encoding/

ПИСЬМО В БУФЕР

если вы записываете в 4-байтовый буфер, символ с кодировкой UTF8, ваш двоичный файл будет выглядеть следующим образом:

00000000 11100011 10000001 10000010

если вы записываете в 4-байтовый буфер, символ с кодировкой UTF16, ваш двоичный файл будет выглядеть так:

00000000 00000000 00110000 01000010

Как вы можете видеть, в зависимости от того, какой язык вы будете использовать в своем контенте, это соответственно повлияет на вашу память.

например. Для этого конкретного символа: Кодировка UTF16 более эффективна, поскольку у нас есть 2 свободных байта для следующего символа. Но это не значит, что вы должны использовать UTF16 для японского алфавита.

ЧТЕНИЕ ИЗ БУФЕРА

Теперь, если вы хотите прочитать вышеуказанные байты, вы должны знать, в какую кодировку он был записан, и правильно его декодировать.

например. Если вы расшифруете это: 00000000 11100011 10000001 10000010 в кодировке UTF16 вы получите , а не

Примечание: Кодировка и Unicode - это две разные вещи. Unicode - это большой (таблица) , каждый символ которого сопоставлен с уникальной кодовой точкой. например Символ (буква) имеет (кодовая точка) : 30 42 (шестнадцатеричный). Кодирование, с другой стороны, представляет собой алгоритм, который преобразует символы более подходящим способом при хранении на аппаратном уровне.

30 42 (hex) - > UTF8 encoding - > E3 81 82 (hex), which is above result in binary.

30 42 (hex) - > UTF16 encoding - > 30 42 (hex), which is above result in binary.

enter image description here

9 голосов
/ 15 января 2014

Почему Юникод? Потому что в ASCII всего 127 символов. Те от 128 до 255 отличаются в разных странах, поэтому есть кодовые страницы. Таким образом, они сказали, что пусть до 1114111 символов. Итак, как вы храните самую высокую кодовую точку? Вам нужно будет хранить его с использованием 21 бита, поэтому вы будете использовать DWORD, имеющий 32 бита и потраченные 11 битов. Поэтому, если вы используете DWORD для хранения символа Юникода, это самый простой способ, потому что значение в вашем DWORD точно соответствует кодовой точке. Но массивы DWORD, конечно, больше, чем массивы WORD, и, конечно, даже больше, чем массивы BYTE. Вот почему существует не только UTF-32, но и UTF-16. Но utf-16 означает поток WORD, а WORD имеет 16 битов, так как же самая высокая кодовая точка 1114111 может вписаться в WORD? Это не может! Поэтому они помещают все, что выше 65535, в DWORD, который они называют суррогатной парой. Такая суррогатная пара - это два слова, и их можно обнаружить, посмотрев на первые 6 бит. Так что насчет utf-8? Это байтовый массив или байтовый поток, но как самая высокая кодовая точка 1114111 может вписаться в байт? Это не может! Ладно, они также вводят DWORD, верно? Или, возможно, СЛОВО, верно? Почти верно! Они изобрели последовательности utf-8, что означает, что каждая кодовая точка выше 127 должна быть закодирована в 2-байтовую, 3-байтовую или 4-байтовую последовательность. Вот Это Да! Но как мы можем обнаружить такие последовательности? Ну, все до 127 является ASCII и является одним байтом. То, что начинается с 110, является двухбайтовой последовательностью, то, что начинается с 1110, является трехбайтовой последовательностью, а то, что начинается с 11110, является четырехбайтовой последовательностью. Остальные биты этих так называемых «стартовых байтов» принадлежат кодовой точке. Теперь в зависимости от последовательности должны следовать следующие байты. Следующий байт начинается с 10, остальные биты представляют собой 6 битов полезной нагрузки и принадлежат кодовой точке. Объедините полезные биты начального байта и следующих байтов, и вы получите кодовую точку. Вот и вся магия UTF-8.

8 голосов
/ 25 марта 2017

Unicode - это стандарт, который отображает символы на всех языках в конкретное числовое значение, называемое Code Points . Это объясняется тем, что он позволяет использовать разные кодировки с использованием одного и того же набора кодовых точек.

UTF-8 и UTF-16 являются двумя такими кодировками. Они принимают кодовые точки в качестве входных данных и кодируют их, используя некоторую четко определенную формулу для получения кодированной строки.

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

Более подробную информацию о Unicode, UTF-8 и UTF-16 вы можете найти в этой статье,

Что должен знать каждый программист о Unicode

4 голосов
/ 06 декабря 2018

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

UTF-8 - Программное обеспечение выделяет от 1 до 4 переменных 8-битных байтов для данного символа. Что здесь подразумевается под переменной? Допустим, вы отправляете символ «A» через ваши HTML-страницы в браузере (HTML - это UTF-8), соответствующее десятичное значение A равно 65, при преобразовании его в десятичное число становится 01000010. Для этого требуется всего 1 байт , 1 байтовая память выделяется даже для специальных принятых английских символов, таких как «ç» в слове «фасад». Однако, если вы хотите хранить европейские символы, требуется 2 байта, поэтому вам нужен UTF-8. Однако, когда вы выбираете азиатские символы, вам нужно минимум 2 байта и максимум 4 байта. Точно так же Emoji требуют от 3 до 4 байтов. UTF-8 удовлетворит все ваши потребности.

UTF-16 выделит минимум 2 байта и максимум 4 байта на символ, он не выделит 1 или 3 байта. Каждый символ представлен 16-битным или 32-битным.

Тогда почему существует UTF-16? Первоначально Unicode был 16 бит, а не 8 бит. Ява приняла оригинальную версию UTF-16.

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

Java-программа, вызываемая веб-браузерами, использует UTF-16, но веб-браузер отправляет символы с использованием UTF-8.

2 голосов
/ 30 августа 2016

UTF расшифровывается как Unicode Transformation Format. В основном в современном мире существуют сценарии, написанные на сотнях других языков, форматы которых не охватываются базовым ASCII, использованным ранее. Следовательно, UTF возник.

UTF-8 имеет возможности кодирования символов, и его кодовая единица составляет 8 бит, в то время как для UTF-16 - 16 бит.

...