UTF-16

UTF-16 ( англ. Unicode Transformation Format ) В інформатики - один із способів кодування символів з Unicode у вигляді послідовності 16 - бітних слів. Дана кодування дозволяє записувати символи Юнікоду в діапазонах U +0000 .. U + D7FF і U + E000 .. U +10 FFFF (всього 1112064 штук). При цьому кожен символ записується одним або двома словами (сурогатна пара).

Кодування UTF-16 описана в додатку Q до міжнародного стандарту ISO / IEC 10646, а також їй присвячено IETF RFC 2781 "UTF-16, an encoding of ISO 10646".


1. Історія появи

Перша версія Юнікоду (1991 р.) являла собою 16-бітну систему кодування з фіксованою шириною символу; загальне число різних символів було 2 16 (65536). У другій версії Юнікоду (1996 р.) було вирішено значно розширити кодову область; для збереження сумісності з тими системами, де вже був реалізований 16-бітний Юнікод, і була створена UTF-16. Область 0xD800-0xDFFF, відведена для сурогатних пар, раніше належала до області "символів для приватного використання".

Оскільки в UTF-16 можна відобразити 20 лютого +2 16 - 2048 (1112064) символів, то це число і було обрано в якості нової величини кодового простору Юнікоду.


2. Принцип кодування

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.. 10FFFF 16. Виключений звідси діапазон D800 16.. DFFF 16 використовується як раз для кодування так званих сурогатних пар - символів, які кодуються двома 16-бітними словами. Символи Unicode до FFFF 16 включно (виключаючи діапазон для сурогатів) записуються як є 16-бітовим словом. Символи ж в діапазоні 10000 16.. 10FFFF 16 (більше 16 біт) вже кодуються парою 16-бітних слів. Для цього їх код арифметично зсувається до нуля (з нього віднімається мінімальне число 10000 16). В результаті вийде значення від нуля до FFFFF 16, яке займає до 20 біт. Старші 10 біт цього значення йдуть в лідируюче (перше) слово, а молодші 10 біт - в подальше (друге). При цьому в обох словах старші 6 біт використовуються для позначення сурогату. Біти з 11 по 15 мають значення 11011 2, а 10-й біт містить 0 у лідируючого слова та 1 - у наступного. У зв'язку з цим можна легко визначити до чого відноситься кожне слово.


3. Порядок байт

Один символ кодування UTF-16 представлений послідовністю двох байтів. Який з двох йде попереду, старший чи молодший, залежить від порядку байтів. Систему, сумісну з процесорами x86, називають little endian , А з процесорами m68k і SPARC - big endian .

Для визначення порядку байтів використовується мітка порядку байтів ( англ. Byte order mark ). На початку тексту записується код U + FEFF. При зчитуванні, якщо замість U + FEFF вважалося U + FFFE, значить порядок байтів зворотний, оскільки символу з кодом і U + FFFE в Юникоде немає. Так як в кодуванні UTF-8 не використовуються значення 0xFE і 0xFF, можна використовувати мітку порядку байтів як ознака, що дозволяє розрізняти UTF-16 і UTF-8.


3.1. UTF-16LE та UTF-16ВE

Передбачена також можливість зовнішнього вказівки порядку байтів - для цього кодування повинна бути описана як UTF-16LE або UTF-16ВE (little-endian / big-endian), а не просто UTF-16. У цьому випадку мітка порядку байтів (U + FEFF) не потрібна.

4. UTF-16 в ОС Windows

В API Win32, поширеному в сучасних версіях операційної системи Microsoft Windows, є два способи представлення тексту: у формі традиційних 8-бітних кодових сторінок і у вигляді UTF-16.

В файлових системах NTFS, а також FAT з підтримкою довгих імен, імена файлів записуються в UTF-16LE.


5. Приклади процедур

Приклади нижче записані на псевдокоді і в них не враховується маска порядку байт - вони лише показують суть кодування. Порядок байт - від молодшого до старшого (Little-Endian, интеловский x86). Тип Word - двобайтове слово (16-бітне беззнакове ціле), а тип UInt32 - 32-бітне беззнакове ціле. Шістнадцяткові значення починаються зі знака долара "$".

5.1. Кодування

У прикладі 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 

5.2. Розкодування

У прикладі 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