UTF-16
- 1 year ago
- 0
- 0
UTF-16 ( англ. Unicode Transformation Format) в информатике — один из способов кодирования символов из Юникода в виде последовательности 16- битных слов.
Данная кодировка позволяет записывать символы Юникода в диапазонах U+0000..U+D7FF и U+E000..U+10FFFF (общим количеством 1 112 064). При этом каждый символ записывается одним или двумя словами (суррогатная пара). Кодировка UTF-16 описана в приложении Q к международному стандарту , а также ей посвящён IETF «UTF-16, an encoding of ISO 10646».
Первая версия Юникода (1991 г.) представляла собой 16-битную кодировку с фиксированной шириной символа; общее число разных символов было 2 16 (65 536). Во второй версии Юникода (1996 г.) было решено значительно расширить кодовую область; для сохранения совместимости с теми системами, где уже был реализован 16-битный Юникод, и была создана UTF-16. Область 0xD800—0xDFFF, отведённая для суррогатных пар, ранее принадлежала к области «символов для частного использования».
Поскольку в UTF-16 можно отобразить 2 20 +2 16 −2048 (1 112 064) символов, то это число и было выбрано в качестве новой величины кодового пространства Юникода.
DC00 | … | DFFE | DFFF | |
---|---|---|---|---|
D800 | 010000 | … | 0103FE | 0103FF |
D801 | 010400 | … | 0107FE | 0107FF |
… | … | |||
DBFF | 10FC00 | … | 10FFFE |
В UTF-16 символы кодируются двухбайтовыми словами с использованием всех возможных диапазонов значений (от 0 до FFFF 16 ). При этом можно кодировать символы Unicode в диапазонах 0000 16 ..D7FF 16 и E000 16 ..FFFF 16 . Исключенный отсюда диапазон D800 16 ..DFFF 16 используется как раз для кодирования так называемых суррогатных пар — символов, которые кодируются двумя 16-битными словами.
Символы Unicode до FFFF 16 включительно (исключая диапазон для суррогатов) записываются как есть 16-битным словом.
Символы же в диапазоне 10000 16 ..10FFFF 16 (больше 16 бит) кодируются по следующей схеме:
Один символ кодировки UTF-16 представлен последовательностью двух байтов или двух пар байтов. Который из двух байтов идёт впереди, старший или младший, зависит от порядка байтов . Систему, совместимую с процессорами x86 , называют little endian , а с процессорами m68k и SPARC — big endian .
Для определения порядка байтов используется метка порядка байтов ( англ. Byte order mark). В начале текста записывается код U+FEFF. При считывании, если вместо U+FEFF считалось U+FFFE, значит порядок байтов обратный (little endian), поскольку код U+FFFE в Юникоде не кодирует символ и зарезервирован как раз для целей определения порядка байтов. Так как в кодировке UTF-8 не используются значения 0xFE и 0xFF, можно использовать метку порядка байтов как признак, позволяющий различать UTF-16 и UTF-8.
Предусмотрена также возможность внешнего указания порядка байтов — для этого кодировка должна быть описана как UTF-16LE или UTF-16BE (little-endian / big-endian), а не просто UTF-16. В этом случае метка порядка байтов (U+FEFF) не нужна.
В API Win32 , распространённом в современных версиях операционной системы Microsoft Windows , имеется два способа представления текста: в форме традиционных 8-битных кодовых страниц и в виде UTF-16.
При использовании UTF-16, Windows не накладывает ограничений на прикладные программы касательно кодирования текстовых файлов, позволяя им использовать как UTF-16LE, так и UTF-16BE посредством установки и трактовки соответствующей метки порядка байтов . Однако внутренний формат Windows — всегда UTF-16LE. Этот момент следует учитывать при работе с исполняемыми файлами , использующими юникодовые версии функций WinAPI. Строки в них всегда кодируются в UTF-16LE .
В файловых системах NTFS , а также FAT с поддержкой длинных имён, имена файлов записываются также в UTF-16LE.
Примеры ниже записаны на псевдокоде и в них не учитывается маска порядка байтов — они лишь показывают суть кодирования. Порядок байтов — от младшего к старшему (Little-Endian, интеловский x86). Тип
Word
— двухбайтовое слово (16-битное беззнаковое целое), а тип
UInt32
— 32-битное беззнаковое целое. Шестнадцатеричные значения начинаются со знака доллара «$».
В примере
WriteWord()
— условная процедура, которая пишет одно слово (при этом сдвигает внутренний указатель). Функция
LoWord()
возвращает младшее слово от 32-битного целого (старшие биты, не глядя, отбрасываются).
// Допустимые значения Code: $0000..$D7FF, $E000..$10FFFF. Procedure WriteUTF16Char(Code: UInt32) If (Code < $10000) Then WriteWord(LoWord(Code)) Else Code = Code - $10000 Var Lo10: Word = LoWord(Code And $3FF) Var Hi10: Word = LoWord(Code Shr 10) WriteWord($D800 Or Hi10) WriteWord($DC00 Or Lo10) End If End Procedure
В примере
ReadWord()
читает слово из потока (сдвигая при этом внутренний указатель). Она же при необходимости может корректировать порядок байтов. Функция
WordToUInt32
расширяет двухбайтовое слово до четырёхбайтового беззнакового целого, заполняя старшие биты нулями.
Error()
прерывает выполнение (по сути
исключение
).
// В случае успеха возвращаются значения // в диапазонах $0000..$D7FF и $E000..$10FFFF. Function ReadUTF16Char: UInt32 Var Leading: Word // Лидирующее (первое) слово. Var Trailing: Word // Последующее (второе) слово. Leading = ReadWord(); If (Leading < $D800) Or (Leading > $DFFF) Then Return WordToUInt32(Leading) Else If (Leading >= $DC00) Then Error("Недопустимая кодовая последовательность.") Else Var Code: UInt32 Code = WordToUInt32(Leading And $3FF) Shl 10 Trailing = ReadWord() If ((Trailing < $DC00) Or (Trailing > $DFFF)) Then Error("Недопустимая кодовая последовательность.") Else Code = Code Or WordToUInt32(Trailing And $3FF) Return (Code + $10000) End If End If End Function