2006-12-06

UNICODE

Одна из многих ошибок Микрософт (и не только Микрософт, кстати) - повсеместное использование UTF-16, как основного представления для UNICODE. Это создает множество неудобств, неэффективностей и иллюзий и не имеет практических преимуществ по сравнению с UTF-8. Вот коротко об этом:

1. Иллюзия, что UTF-16 покрывает весь диапазон символов -- это не так, есть Unicode Surrogates, которые представляют один символ при помощи двух
2. Аналогично, UTF-16 -- не код фиксированной длины, символ может кодироваться одним или двумя словами
3. Иллюзия, что можно использовать привычную логику в UTF-16 программах и они сразу будут работать со многими языками -- не так, есть столько сложностей с сортировкой и сравнением, с преобразованием чисел и поиском знаков пунктуации, что реально это не работает. Реально можно сортировать и искать только то, что известно. Обычно программы работают посимвольно только с символами ASCII, а остальные unicod-ную подстроки передают как-есть в компоненты, которые знают что с ними делать, например, для отрисовки на экране.
4. Иллюзия, что UTF-16 самодостаточна -- не так, обычно всё равно надо знать Locale или Culture, т.е. язык, который это всё породил. Только тогда можно сделать Case-Insensitive сравнение. Известный пример с турецким "i".
5. Иллюзия, что с UTF-8 работать сложнее, чем с UTF-16. Это не так. Все символы стандартного набора ASCII - точно такие же и в UTF-8. А все многобайтные символы не имеют в своем представлении байтов из нижней половины ASCII, поэтому работать с UTF-8 можно точно так же, как и с обычной символьной строкой. Так же искать null-terminator, так же искать любой ASCII символ, так же делить на кусочки, сохранять в файле и т.д. Главное - воспринимать многобайтовую юникодную часть строки как черный ящик, передавая ее без изменения из одного места в другое.
6. Иллюзия, что работать с UTF-8 медленнее. На самом деле быстрее. Код x86 процессоров короче и быстрее, когда работает с байтами и с 4-байтовыми словами. 2-байтовый режим - самый медленный. В большинстве случаев совершенно не надо просматривать строку по юникодным символам, вполне достаточно итеррировать побайтно.
7. UTF-8 длиннее, чем UTF-16. Вовсе нет. Чаще короче. Попробуйте сами сохранить в notepad-е и увидите.

Короче, вот мой вывод: любой текст написан на некотором языке. Если мы скармливаем текст машине, то в нем есть части написанные на языке понимаемом машиной, а есть части, написанные для человека. Например comma-separated - запятые и возвраты каретки - это машинный синтаксис, а строки между ними не используются ни для чего, кроме того, что показываются человеку (возможно ещё используются числа в оговоренном формате, тогда это тоже входит в "машинный" язык).

Первое правило
: не включайте не-ASCII символов в описание "машинной" части языка. Человеческая часть вполне может содержать юникод, но она должна быть ограничена ASCII-символами.
Второе:
старайтесь избегать обработки "человеческой" части в своей программе. Пусть это будет черный ящик, иероглиф, который передается как-есть с ввода на вывод, а если надо вызовите системный компонент для этих операций.
Третье:
бойтесь case-insensitive. Пусть будет case-sensitive. Это причиняет меньше неудобств, чем создает проблем.
И четвертое: В большинстве случаев лучше писать юникодные программы, используя UTF-8.

Почему же Микрософт использует UTF-16? Приверженцы conspiracy бы сказали, что им доплачивают производители памяти. Я бы считал, что скорее из за невежества (как, впрочем, объясняются и все остальные заговоры). В большинстве unix/linux подобных систем используется как раз UTF-8.

Больше информации здесь:
http://en.wikipedia.org/wiki/UTF-8
http://www.cl.cam.ac.uk/~mgk25/unicode.html

No comments: