вторник, 2 марта 2010 г.

Не спускайте глаз с кодовой страницы

Это перевод Keep your eye on the code page. Автор: Реймонд Чен.

Вспомните, что существует, как правило, две активно используемые 8-разрядные кодовые страницы: так называемая кодовая страница "ANSI" и так называемая кодовая страница "OEM". GUI программы обычно используют кодовую страницу ANSI для 8-битных файлов (хотя UTF-8 и становится все более популярным в последнее время), в то время как консольные программы обычно используют кодовую страницу OEM.

Это означает, например, что при открытии 8-битного текстового файл в Блокноте, Блокнот предположит кодовую страницу ANSI. Но если вы используете команду type в командной строке, то она будет использовать кодовую страницу OEM.

Это имеет интересные последствия, если вы часто переключаетесь между графическими и консольными приложениями.

Обе кодовые страницы обычно соглашаются друг с другом по первым 128 символах, но они почти всегда не согласны с символами от 128 до 255 (так называемыми "расширенными символами"). Например, на машине US-English символ #$80 в кодовой странице OEM - это Ç, а в кодовой странице ANSI - это €.

Рассмотрим каталог, который содержит файл с именем "Ç". Если вы введёте "dir" в командной строке, то вы увидите на экране Ç. С другой стороны, если вы сделаете "dir > files.txt" и откроете files.txt в редакторе GUI (например, Блокноте), то вы обнаружите, что Ç был изменён на €, поскольку символ #$80 в файле был истолкован как символ в кодировке ANSI вместо кодовой страницы OEM.

Еще более странно, что если вы отметите/выберите имя файла из окна консоли и вставите его в Блокнот - то вы получите Ç. Это потому, что код выделения текста окна консоли сохраняет текст в буфере обмена в формате Unicode; символ сохраняется в буфере обмена не как #$80 (1-байтовый символ), а как #$00C7 (2-байтовый символ) - кодовая точка Unicode для "Latin Capital Letter C With Cedilla". Когда этот символ вставляется в Блокнот, он будет автоматически преобразован из Unicode в кодовую страницу ANSI, которая на US-English системе кодирует Ç в символ с кодом #$C7.

Но подождите, это еще не все. Командный процессор имеет опцию (/U) для получения всего перенаправленного ввода-вывода в Unicode, а не кодовую страницу OEM.

(Замечу, что встроенная документация командного процессора говорит, что переключатель /A включает вывод в ANSI - это неправильно. /A выводит текст в кодировке OEM. Это одна из тех ошибок, которые вы узнаете мгновенно, если вы знаете, что происходит. Это настолько очевидно OEM, что, когда я вижу в документации "ANSI", мой разум просто читает это как "OEM". Точно так же носители английского языка часто не замечают ошибки произношения или удвоенные слова).

Если вы запустите команду
CMD /U /C dir ^> files.txt
то на выходе будет Unicode, и поэтому символ Ç будет записан как #$00C7, который затем будет корректно прочитан Блокнотом.

Это имеет серьезные последствия для пакетных (batch) файлов.

Командные файлы являются 8-битными файлами и интерпретируются в зависимости от набора символов OEM. Это означает, что если вы пишете пакетный файл в Блокноте или какой-либо другой программе, использующей набор символов ANSI для 8-битных файлов, и командный файл содержит расширенные символы (например, кириллицу), то получаемый вами результат не будет соответствовать тому, что вы видите в редакторе.

Почему имеется это расхождение между программами с графическим интерфейсом и консольными программами над тем, как следует толковать 8-битные символы?

Причина, конечно же, историческая.

Вернёмся во времена MS-DOS: была одна кодовая страница - та, что сейчас называется OEM. Для US-English систем это кодовая страница с символами псевдо-графики и фрагментами интегральных знаков. В ней содержатся подчёркнутые (accented) буквы, но не очень большой набор - вполне достаточно для покрытия немецкого, французского, испанского и итальянского языков. И шведского (почему шведский, а не датский или норвежский - я не знаю).

Когда пришла Windows, ей больше не нужны были символы псевдо-графики, поэтому было решено, что они тратят ценное пространство, которое может быть использовано для добавления еще больше букв других языков, поэтому символы псевдо-графики были выброшены, а вместо них были добавлены символы для датского, норвежского, исландского и канадского французского (да, канадский французский использует символы, которых нет в европейском французском).

Так начался раскол между консольными программами (MS-DOS) и программы с графическим интерфейсом (Windows) по тому, как следует толковать 8-разрядные символьные данные.

Комментариев нет:

Отправить комментарий

Можно использовать некоторые HTML-теги, например:

<b>Жирный</b>
<i>Курсив</i>
<a href="http://www.example.com/">Ссылка</a>

Вам необязательно регистрироваться для комментирования - для этого просто выберите из списка "Анонимный" (для анонимного комментария) или "Имя/URL" (для указания вашего имени и ссылки на сайт). Все прочие варианты потребуют от вас входа в вашу учётку (поддерживается OpenID).

Пожалуйста, по возможности используйте "Имя/URL" вместо "Анонимный". URL можно просто не указывать.

Ваше сообщение может быть помечено как спам спам-фильтром - не волнуйтесь, оно появится после проверки администратором.