многоликий Unicode
От: Кодт Россия  
Дата: 03.10.03 08:06
Оценка: 148 (24)
#Имя: FAQ.winapi.ManySidedUnicode
Здравствуйте, Аноним, Вы писали:

А>Блин, запутался совсем! Всегда считал, что Unicode-кодировка это просто 2 байта на символ. Причем существует только одна кодовая таблица, в которой содержаться алфавиты всех языков мира + еще всякие вспомогательные символы.


А>А тут еще всяки utf-7, utf-8... Это что за черти такие? Помогите разобраться


Юникод — это свод значений (смыслов) и изображений всевозможных символов, включая типографские знаки, управляющие символы, и т.п.

Все символы пронумерованы, т.е. им сопоставлены числовые значения. Таблица нумерации называется UCS (Unicode Character Set): есть UCS-2 (емкостью до 2^16 символов) и UCS-4 (до 2^64 штук).
Естественно, что ASCII <= UCS-2 <= UCS-4, т.е. они включают друг друга.

Способы кодирования строки символов — варьируются.
Среди них стандартом зафиксированы кодировки UTF (Unicode Text Format)
* UTF-32: на один символ по 4 байта, что позволяет кодировать весь диапазон UCS-4 одним элементом. Т.е. сколько символов, столько и элементов в строке.
* UTF-16: на один символ по 2 байта. Достаточно для равномерного кодирования диапазона UCS-2; чтобы кодировать UCS-4 — используется мультиворд (по аналогии с мультибайтом): префиксное слово и до двух слов расширения.
* UTF-8: на один символ от 1 байта (в диапазоне ASCII, т.е. 0-127) до 3 байт (весь диапазон UCS-2) и даже до 5 байт (UCS-4).
* UTF-7: строка кодируется 7-битными элементами, причем даже для ASCII приходится потратить до 2 элементов. Весь UCS-4 кодируется то ли 7, то ли 9 элементами (не помню).

Зачем такое разнообразие?

UTF-7 создан для работы со строками в 7-битных средах (телетайпы, электронная почта). Вся закодированная строка состоит из печатных символов. В принципе, можно было бы взять UTF-16 и законвертировать его в Base64 или UUEncode, примерно с тем же эффектом. Однако UTF-7 дает более компактные строки.

UTF-8 удобен тем, что на ASCII тратится ровно 1 байт, при этом получается вполне читаемый текст. Это нормальная мультибайтная кодировка, и с кодированными строками можно работать как обычно (в том числе — с концевым 0), в отличие от UTF-16, UTF-32 (где каждый второй байт может быть 0).
Альтернатива UTF-8 — это текст HTML, где все символы за пределами ASCII кодируются знаком &#nnnnn;. Очевидно, что UTF-8 компактнее.

Еще одно удобство UTF-7 и UTF-8 — независимость от порядка байтов в слове. Об этом — ниже.

UTF-16 — его преимущество аналогично UTF-8: самый популярный диапазон, т.е. UCS-2, кодируется одним двухбайтным словом. Для экзотических кодовых страниц (за пределами UCS-2), конечно, придется повыкручиваться, но это редкость.
Большее (по сравнению с байтовыми кодировками) потребление памяти уравновешено большей скоростью обработки (мультибайт/мультиворд медленнее однобайта/одноворда).

UTF-32 — скорость обработки ставится на первое место, в ущерб памяти.

Теперь о порядке байтов.
Поскольку минимально адресуемая величина — это байт, то (особенно при записи в файл) окажется, что слово UTF-16 или UTF-32 можно записать 2 разными способами: младшими байтами вперед либо старшими:
0x1234 -> 0x12, 0x34 (big endian)
0x1234 -> 0x34, 0x12 (little endian)
Исторически сложилось, что в интернете используется big endian — из-за того, что компьютеры Digital Equipment (PDP, VAX) были более распространены.
А у Intel внутреннее представление little endian. (На мой взгляд, оно более логично; но когда создавался DEC, меня еще не было ). Соответственно, little endian — стандарт для Windows.

Для того, чтобы понять, как же закодирован (LE|BE) файл в UTF-16, который мы получили со стороны — в его начало приписывается специальный признак: число 0xFEFF.
Если кодировка little endian, то это будут байты 0xFF, 0xFE (по-русски — "яю").
Если big endian — 0xFE, 0xFF (соответственно, "юя").

К этому тексту есть дополнения/исправления от других участников, просмотрите их.
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.