Здравствуйте, Аноним, Вы писали:
А>Блин, запутался совсем! Всегда считал, что 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 (соответственно, "юя").
К этому тексту есть дополнения/исправления от других участников, просмотрите их.