UTF-8 (от англ. Unicode Transformation Format, 8-bit — «формат преобразования Юникода, 8-битный») — одна из общепринятых и стандартизированных кодировок текста, которая позволяет хранить символы Юникода.
Стандарт UTF-8 официально закреплён в документах RFC 3629 и ISO/IEC 10646 Annex D. Кодировка нашла широкое применение в UNIX-подобных операционных системах и веб-пространстве. Сам же формат UTF-8 был изобретён 2 сентября 1992 года Кеном Томпсоном и Робом Пайком и реализован в Plan 9. В качестве BOM использует последовательность байт EF16, BB16, BF16 (что у неё самой является трёхбайтовой реализацией символа FEFF16).
Одним из преимуществ является совместимость с ASCII — любые их 7-битные символы отображаются как есть, а остальные выдают пользователю мусор (шум). Поэтому в случае, если латинские буквы и простейшие знаки препинания (включая пробел) занимают существенный объём текста, UTF-8 даёт выигрыш по объёму по сравнению с UTF-16.
Алгоритм закодирования в UTF-8 стандартизирован в RFC-3629 [7] и состоит из 3-х пунктов:
( Для номеров с U+0000 по U+007F кодировка UTF-8 полностью соответствует 7-битному US-ASCII c 0 в первом бите и занимает один октет(байт). )
1. Определить количество октетов(байт), требуемых для данного (кодируемого) номера символа (c U+0100 по U+10FFFF) и первый столбец в таблице выше([7]). Очень важно отметить, что строки таблицы являются взаимоисключающими, т.е.: Есть Только Один Правильный способ кодирования данного символа.
2. Подготовить старшие биты первого октета (отвечающие за число октетов), как во втором столбце таблицы (110xxx -два октета, 1110xxx -три, 11110xx -четыре).
3. Заполнить оставшиеся (от старших) биты (отмечены х) в найденных в П.1 октетах, номером символа (U+nnnnn), выраженном в двоичном виде. Начать с младших битов номера символа, поставив их в младшие биты последнего октета кода. И так далее, пока все биты номера символа не будут перенесены в Свободные биты октетов. Подробнее: смотри RFC-3629
1. Если размер символа в кодировке UTF-8 = 1 байт Код имеет вид (0aaa aaaa), где «0» — нулевой бит, остальные биты «a» — это код символа в кодировке ASCII;
2. Если размер символа в кодировке в UTF-8 > 1 байт (то есть от 2 до 6): 2.1 Первый байт 2.1.1 содержит количество байтов символа, закодированное в единичной системе счисления; 2 — 11 3 — 111 4 — 1111 5 — 1111 1 6 — 1111 11 2.1.2 «0» — бит-терминатор, означающий завершение кода размера 2.1.3 оставшиеся биты — значащие 2.2 далее идут значащие байты кода, которые имеют вид (10xx xxxx), где «10» — биты признака продолжения, а x — значащие биты.
В общем случае варианты представления одного символа в кодировке UTF-8 выглядят так: (1 байт) 0aaa aaaa (2 байта) 110x xxxx 10xx xxxx (3 байта) 1110 xxxx 10xx xxxx 10xx xxxx (4 байта) 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx (5 байт) 1111 10xx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx (6 байт) 1111 110x 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx
Пример
Код BOM для UTF-8 = EF BB BF(16) = 1110 1111 1011 1011 1011 1111(2)
Значащие биты в форме записи UTF-32BE располагаются подряд, начиная с заполнения младшего байта. Задача преобразования UTF-32BE в UTF-8 сводится к выбору соответствующей формы UTF-8 и копированию значащих битов UTF-32BE без каких либо дополнительных преобразований. Очень часто требуется проверять наличие старших битов числа. Следующий код на языке Си исключает случайные описки при наборе маски #define UTF8_MASK( bits ) ( ~(( int )0) << bits )
if ( !( value & UTF8_MASK( 7 ) ) ) // 7 - количество значащих бит. // Можно подставлять также: 11, 16, 21, 26, 31. { // Выполняется, если у числа нет битов, установленных в "1", кроме младших 7 } Предыдущий код будет заменен препроцессором на этот: if ( !( value & 0xFFFFFF80 ) ) {
}
Отличительные значения байтов представлены в первую очередь для использования в алгоритмах автоматического определения кодировки текста. Первичным признаком можно считать BOM, которая повышает вероятность использования той или иной кодировки (см. отдельную статью). Другим признаком является обнаружение не валидных или сильно маловероятных байт, или же наоборот вероятных. Здесь же следует отметить, что UTF-8 поддерживает кодирование 31-битных кодов UCS-4. Если речь касается символов Unicode, то пяти- и шестибайтовые значения оказываются сильно маловероятными. И есть ещё один примечательный момент — в кодировке UTF-8 возможно избыточное кодирование, что порождает многозначность. Например, ASCII-символ можно закодировать шестью вариантами байтовых последовательностей, но это не означает не валидность избыточных байтовых последовательностей. И здесь можно впасть в заблуждение когда первый байт содержит только нулевые биты значения — для последовательностей выше двух байт исключительно это нормально.
Все значения представлены в шестнадцатеричной системе счисления. Под значением «сильно маловероятен» в колонке «статус» следует рассматривать использование кодировщика, который не отбрасывает лидирующие нули.
Примеры ниже приведены для быстрой ориентации в случаях некорректного декодирования текста (так называемые кракозябры[en]).
Так выглядит фраза «Человек сейчас увидит лишь то, что ожидает увидеть.» если она воспринята декодировщиком в кодировке Windows-1251, а не UTF-8:
Самосинхронизацию в UTF-8 можно рассмотреть когда вашей программе подаются случайные байты и вам нужно определить начало первого символа. Первичным признаком является сброшенный старший бит байта — это ASCII-символ. Если же он установлен, то пропускаем те байты, у которых сброшен бит перед старшим. В остальных случаях можно продолжать посимвольное поточное раскодирование.
UTF-8 обладает свойством самосинхронизации при обработке 8-битными байтами. Альтернативной UTF-8 является кодировка UTF-16, которая уже обрабатывается 16-битными словами. Возможно возникновение сомнения что UTF-16 не является самосинхронизирующейся. В настоящий момент передача данных в компьютере в подавляющем большинстве производится цельными октетами — 8 бит или ничего (см. IPv4, IPv6, SATA для современной аппаратуры и ATA с PATA для недавней). В данных условиях UTF-8 имеет преимущество в характеристике самосинхронизации перед UTF-16, если речь касается аппаратной передачи данных или работы с байтовым потоком (чтение Unicode-данных с произвольной позиции). Если же работа осуществляется в оперативной памяти одной машины, то UTF-16 так же является самосинхронизирующейся (если аппаратура способна подавать цельные 16-битные слова).