Юникод и байты

Иван Сагалаев

Про Юникод написано много, но мне кажется, что это одна из тем, про которую "чисто ради интереса" никто читать не полезет. Поэтому я решил поделиться здесь одной штукой, которая, как я в разговорах со многими замечал, не всем известна. Речь о том, "сколько байт занимает юникод".

Старые кодировки (например WINDOWS-1251, KOI8-R) совершенно четко определяют, какие конкретные значения одного байта используются для кодирования одного символа (человеческого или служебного). И отсюда вытекает их известная проблема с тем, что они не могут кодировать больше 256 символов. Для того, чтобы с этой проблемой бороться универсально, был придуман Юникод.

Вот дальше идет то самое частое, потому что очень логичное, заблуждение о том, что Юникод -- это кодировка, где для каждого символа отводится 2 байта, а значит она может кодировать 65536 символов. Больше того, хоть я и не смотрел специально, кажется именно так она и была задумана в самом начале. Но сейчас все совсем не так.

Довольно быстро возникла необходимость кодировать гораздо больше, чем 65536 символов (чуть больше миллиона сейчас) и, что главное, появилась необходимость кодировать их по-разному. Поэтому в отличие от старых кодировок стандарт Юникода полностью разделяет две вещи:

* номера, присваиваемые символам
* какими байтами эти номера представляются

Номера, присваиваемые символам, полностью абстрактны. Это не байты, не двубайты, а просто числа. Например символу "Заглавная кириллическая буква А" назначен номер 1040, он же -- 410 в шестнадцатеричной системе. И формально в Юникоде это принято записывать как U+0410.

А вот способов представлять это число в памяти или записывать в файлы существует больше одного. Называются они "формы кодирования". Вот наиболее распространенные.

UTF'ы

Есть несколько форм кодирования, которые официально входят в стандарт.

UTF-8

В этой форме юникодные символы кодируются одиночными байтами. Но поскольку одного байта для кодирования миллиона символов слегка мало, разные символы кодируются разным количеством байтов. Те, которые входят в старый ASCII, кодируются одним байтом и их значения полностью с ASCII совпадают. Русские и, например, западноевропейские символы кодируются двумя байтами, японские катакана и хирагана -- тремя, а есть еще всякая экзотика, где могут быть и четыре байта.

UTF-8 совместим со старым софтом и протоколами, потому что в такой строке не может встретиться байт 0x00, который бы ее обрывал. Также в большинстве текстов файлов конфигураций и исходников программ, которые традиционно состоят в основном из ASCII, он не занимает сильно больше места, чем ASCII -- тот же байт на символ. Еще один плюс -- у него нет разных вариантов для разных платформ, он везде одинаковый.

Самый существенный его минус -- это то, что по количеству байт в строке невозможно определить ее длину в символах.

UTF-16 (или, что почти одно и то же -- UCS-2)

Это, собственно, то, с чего начинался Юникод: для кодирования одного символа используются двухбайтовые целые. Этого хватает для того, чтобы хранить большинство нужных и распространенных на практике символов. И только для редких символов, включенных в Юникод позднее, используются пары двухбайтовых целых.

Кстати, UCS-2 -- это как раз UTF-16 без этих дополнительных символов, то есть строго символ = 2 байта.

На практике редкие символы действительно редки (часто встречались с древнегреческой музыкальной грамотой?), поэтому во многих системах для внутреннего представления символов используется именно UTF-16, например в NTFS для имен файлов, в Delphi для WideString'ов, и Java, насколько я знаю, тоже внутри вся в UTF-16 работает со строками.

Однако двухбайтовость делает затруднительным использование UTF-16 для обмена данными из-за двух проблем: наличия нулевых байтов в строке и разночтения порядка следования старшего и младшего байтов на разных платформах.

UTF-32 (или, что почти одно и то же -- UCS-4)

Это -- форма для перфекционистов. Для представления символа используется строго 4 байта, которыми можно представить абсолютно любой юникодный символ. С недавнего времени тот же Python на большинстве платформ использует именно четырехбайтовое представление для юникодных строк.

Отличия от UCS-4 совсем умозрительные и непрактические.

Минус у этого представления, помимо плохой переносимости, как у UTF-16, еще и в том, что UTF-32 попросту занимает еще больше места.

Другие формы

Помимо UTF'ов, внесенных в стандарт Юникода, существует еще несколько знакомых многим способов представления юникодных номеров.

В первую очередь это XML и HTML со своими А и . Такое представление, хоть и занимает места еще больше, чем UTF-32 (по 7 байт в двух предыдущих примерах), зато обладает несомненным плюсом в том смысле, что их можно использовать, даже если вы храните сам файл в старой однобайтовой кодировке. А вот если у вас файл и так хранится в одном из юникодных представлений (UTF-8 чаще всего), то в него можно вставлять все стрелочки и кавычечки прямо в UTF-8, которые можно либо взять из charmap'а, либо сам редактор может уметь обрабатывать всякие мудреные комбинации клавиш для этого. Оно и выглядит более читаемо при этом.

Ну и еще напоследок -- представление в Javascript. Суть та же, что и у (X|HT)ML'а, только запись другая: u0410, u0160...

То, что я тут написал -- довольно упрощенное прдставление, где я не касался всяких форм нормализации, символов, которые не символы, и прочих "высших и низших суррогатов". Хотя вчера успел совершенно замучить жену цитатами из стандарта Юникода, который читал, чтобы уточнить пару вещей для статьи. Штука, конечно, интересная, но удивительно запутанная. Если кого это все заинтересует, то лучше всего начать со статьи про Юникод в русской Wikipedia (очень хорошая).
 (голосов: 4)
Автор: user | Дата: 6 января 2009 | Просмотров: 1473 Коментарии: 2
#1 написал: Nyomas (6 января 2009 15:24)
Весьма пользительно, спасибо
    #2 написал: keche (21 января 2009 01:09)
    Клин - клином вышыбают, а код - кодом wink

    Марийские и русские буквы будут отображаться на mail.ru, myspace.com, если вы будете писать через h t t p :// w w w . glittergraphics . us, где скопирутете html код вашего текста и вставите в окно вами отправляемого сообщения. Много ума для этого не надо, да и знания английского не особо важны. Вы просто открываете сайт и там пишете хоть на китайскoм всё что хотите слева от слова "text", а потом нажимаете "submit", чтобы код получить. Не удивляйтесь, если увидите бегущую строку, она совсем не отобразится в вашем письме. Хорошая вещь, но только вставляются туда короткие словосочетания. Но это тоже не проблема. Вы можете хотя бы одно слово на марийском там написать, получить к нему код, потом тот код скопировать, в нём вы увидите то марийское слово, к которому вы только присоединяете всё что хотите добавить на том же марийском или китайском языке!
    Выглядеть будет так:
    <MARQUEE WIDTH="100%" BEHAVIOR="scroll" SCROLLAMOUNT="5" DIRECTION="left"> .......Здесь введите ваш текст....... </MARQUEE>
    Здорово, что html коды mail.ru поддерживает!
    Главное, не забыть про < / MARQUEE > в конце, т.к. он предназначен для сохранения кода:-)
    Вот ещё проще вариант: благо Марийский язык в основной своей массе включает буквы Кириллицы, а наши буквы вот таким кодом можно писать ӱ ( & # 1265; ), ӧ ( & # 1255;) ҥ ( & # 1189;)
    Tепрь можно по-марийски писать повсюду на mail.ru! Я увлеклась всякими компьютерными штучками и бестящими словами:-) на w w w. gifr.ru можно блестящими русскими буквами писать!
    Пытайтесь, и у вас что-нибудь получится!
        • Для того чтобы написать комментарий к этой новости, пожалуйста, нажмите сюда.


        Яндекс.Погода
        Вы знаете что такое "Электронное правительство"?
        Да
        Нет
        Только слышал об этом
        Архив новостей
        Популярные новости