Рубрика:
Карьера/Образование /
Пятая пара
|
Facebook
Мой мир
Вконтакте
Одноклассники
Google+
|
ВЛАДИМИР ЗАКЛЯКОВ, советник налоговой службы 2-го ранга, zaklyakov@samag.ru
Лабораторная работа Представление текстовой информации в ЭВМ. Часть 1
Теоретические сведения о способах представления текстовой информации в памяти ЭВМ, в том числе и кириллицы
В теоретической части работы рассматриваются вопросы кодирования текстовой информации и некоторые полезные свойства кодировок. Вопросы упаковки, сжатия и оценки количества информации не затрагиваются.
В последующей, практической, части предлагается самостоятельно выполнить несколько заданий посредством общения с компьютером через интерфейс командной строки (CLI), что поможет закреплению теоретических знаний и получению соответствующих навыков работы в консоли.
Описание лабораторного стенда
Для работы требуется ОС Linux, имеющая в своём составе командный интерпретатор bash, утилиты и команды iconv (обычно пакет glibc-common), cat, od, echo, cp, mv, rm, dd (пакет coreutils), dos2unix и unix2dos (пакет dos2unix). Для дополнительного задания повышенной сложности понадобится утилита strings (пакет binutils). Фактически это может быть любой Linux, UNIX или совместимая с ними ОС.
Краткие теоретические сведения
Так как большинство современных ЭВМ (если не сказать, что почти все) удовлетворяет принципам вычислительной машины фон Неймана, то логично предположить, что информация, которую они хранят, обрабатывают и передают по сетям, удовлетворяет принципу двоичного кодирования, а именно представима в виде двоичных чисел.
Существуют международные стандарты и методы кодирования текстовой, числовой, изобразительной, звуковой и видеоинформации. Сегодняшний список видов информации, существующих стандартов и методов, несомненно, может быть расширен в будущем.
Если вопросы представления чисел в памяти ЭВМ были рассмотрены в [1], то данная работа посвящена проблемам хранения текстовой информации. Понимание принципов кодирования и знание основных кодовых таблиц важно не только системным администраторам, но и пользователям для правильного чтения как информации, добытой из Интернета, электронной почты, так и файлов, полученных через внешние носители и др.
Зарождение кодировок
Чтобы лучше понять принципы кодирования текстов, перенесёмся во времена, когда ЭВМ только появлялись, а их базовые принципы ещё не были чётко сформулированы. А если их нет, то давайте их и придумаем вместе. Итак, исходные условия: мы имеем несколько букв (алфавит) и желание представить его в виде цифр, так как цифры [2] «хранить» в памяти ЭВМ мы уже научились. Первое, что обычно приходит на ум, – закрепить за каждым символом алфавита числовой номер – код. Например, 1 для буквы «а», 2 пусть обозначает букву «б», 3 – букву «в» и т.д. Наверняка среди читателей найдутся те, кто в детстве играл подобным образом.
Хоть мы великая страна с наибольшим числом часовых поясов, и нам есть, чем гордиться, всё же мы не были первыми, кто использовал ЭВМ и придумывал способы представления текстов, поэтому первично кодированию подверглись латинские символы, цифры и различные знаки препинания, а не кириллица. Так, в англоязычных странах используются 26 прописных и 26 строчных букв (A… Z, a… z), девять знаков препинания (. , : ! " ; ? ( ) ), пробел, 10 цифр, пять знаков арифметических действий (+, -, *, /, ^) и ряд специальных символов (№, %, _, #, $, &, >, <, |, \); все они и были закодированы – в итоге набралось чуть больше 100 символов. (Дефис, тире, длинное тире и минус были закодированы как «чёрточка» одного вида.) Для кодирования такого числа вариантов можно ограничиться семиразрядным двоичным числом (от 0000000 до 1111111, в десятичной системе счисления – от 0 до 127), что и было сделано.
Кодовые таблицы
Для кодирования букв и других символов, используемых в печатных документах, необходимо закрепить за каждым символом числовой номер – код.
Первой семиразрядной кодовой таблицей была ASCII (American Standard Code for Information Interchange), опубликованная как стандарт ASA X3.4-1963 в июне 1963 года американской организацией по стандартизации American Standards Association (ASA), которая позднее стала именоваться ANSI [3]. (Поэтому данную семибитную кодовую таблицу по появлении называли также ANSI, однако на сегодня термин «кодировка ANSI» не устоялся, в ряде случаев под ним могут пониматься совсем другие кодировки, вплоть до ISO/IEC 8859-1.) Таблица содержала 32 кода команд или управляющих символов (от 0 до 31), большая часть которых сегодня не применяется пользователями, и 95 кодов (от 33 до 127) для различных знаков, достаточных для работы с английскими текстами, как показано в таблице 1 (а, б).
Таблица 1а. Семибитная кодовая таблица ASCII (ANSI)
Таблица 1б. Семибитная кодовая таблица ASCII (ANSI)
Там же (таблица 1а) символы построчно имеют следующие коды в шестнадцатеричной системе счисления (в скобках – в десятичной):
- 1-я строка с 00 по 0F и далее (правая колонка) с 10 по 1F (0–15, 16–31);
- 2-я строка с 20 по 2F и 30 – 3F (32–47, 48–63);
- 3-я строка с 40 по 4F и 50 – 5F (64–79, 80–95);
- 4-я строка с 60 по 6F и 70 – 7F (96–111, 112–127).
Интересное свойство
a + 3210 = A, b + 3210 = B, … , z + 3210 = Z
A - 3210 = A, b - 3210 = B, … , z - 3210 = Z
В таблице 1а для преобразования прописных букв в строчные достаточно к коду буквы прибавить 3210 (1000002) и, наоборот, для преобразования строчных в прописные из кода буквы вычесть 3210. На практике чаще используют не сложение и вычитание, а «побитовое ИЛИ» с числом 001000002 или «побитовое И» с числом 110111112 соответственно. Повторное применение побитовых операций не оказывает никакого влияния на результат, чего не скажешь об операциях сложения и вычитания. Наглядно это можно увидеть, если сделать таблицы с символами в 32 колонки. Тогда вышестоящие символы от нижестоящих будут отличаться ровно на 32 позиции (см. таблицу 1а).
Однако на практике использовать такую таблицу для преобразований шестнадцатеричных значений в вид символа и обратно не очень удобно, поэтому чаще можно увидеть таблицу с 16 колонками (таблица 1б).
В последующем данная ASCII таблица была принята как стандарт ведущими международными организациями по стандартизации [1]:
- ISO/IEC 646:1991 [8];
- ITU-T Recommendation T.50 (09/92) [9], ECMA-6 (European Computer Manufacturers Association).
Русификация
Однако для нашей страны и многих других стран необходимо было добавить в кодовую таблицу символы национальных алфавитов. Для этого было предложено использовать восьмибитную кодовую таблицу, которая могла содержать дополнительно ещё 128 символов (с 128 по 255).
В дальнейшем был принят стандарт на восьмибитную таблицу ASCII – ISO/IEC 8859, в которой первые 128 символов оставались теми же, что и в семибитной таблице, а символы с 128 по 255 отводились для неанглийских символов [1].
Существует несколько частей этого стандарта:
- ISO/IEC 8859-1:1998 – Part 1: Latin alphabet № 1;
- SO/IEC 8859-5:1999 – Part 5: Latin/Cyrillic alphabet;
- ISO/IEC 8859-6:1999 – Part 6: Latin/Arabic alphabet;
- ISO/IEC 8859-7:2003 – Part 7: Latin/Greek alphabet;
- ISO/IEC 8859-8:1999 – Part 8: Latin/Hebrew alphabet и т.д.
В таблице 2 представлена вторая половина кодовой таблицы (коды 128–255) для стандарта ISO 8859-5.
Таблица 2. Кодовая таблица ISO 8859-5 (коды с 12810 по 25510)
Первые русские ЭВМ использовали семибитную кодировку символов КОИ-7 (Код Обмена Информацией семибитный, см. таблицу 3), в которой присутствовали прописные латинские буквы, а на месте строчных латинских были русские прописные буквы (кириллица).
Таблица 3. Семибитная таблица символов КОИ-7
Позднее на первых отечественных персональных компьютерах использовалась так называемая «Основная кодировка ВЦ Академии наук СССР», в руководствах к старым матричным принтерам обозначаемая просто как «ГОСТ» – восьмибитная кодовая таблица, вторая половина которой содержала символы псевдографики, русские прописные и строчные буквы (коды с 128 по 255 – см. таблицу 4).
Таблица 4. Кодировка символов «ГОСТ» (коды с 12810 по 25510)
В дальнейшем основной кодировкой русских букв для первой операционной системы ПК – MS DOS стала «Альтернативная кодировка ВЦ Академии наук СССР» (вторая половина таблицы для кодов 128-255 приведена в таблице 5). Содержит псевдографику (позволяющую в текстовом режиме рисовать рамки из одинарных и двойных линий). Существует несколько модификаций, отличающихся символами в последних 14 позициях. Зарегистрирована в IANA [5] как IBM 866 или CP866.
Таблица 5. Таблица символов DOS Cyrillic (CP866, коды с 12810 по 25510)
С широким распространением операционной системы Microsoft Windows и появлением её национальных локализаций для второй половины таблицы ASCII было введено понятие «кодовая страница» (code page, CP). Полная таблица кодовых страниц Microsoft Windows велика, поэтому в таблице 6 приведено лишь несколько наиболее важных кодировок.
Таблица 6. Некоторые национальные кодовые страницы (CP – code page) операционной системы Microsoft Windows
Локализация |
ANSI CP |
Mac CP |
DOS (OEM) Primary CP |
DOS (OEM) Secondary CP |
English (United States) |
1252 |
10000 |
437 |
850 |
English (Britain, Canada и др.) |
1252 |
10000 |
850 |
437 |
French (Standard) |
1252 |
10000 |
850 |
437 |
German (Standard) |
1252 |
10000 |
850 |
437 |
Russian |
1251 |
10007 |
866 |
855 |
Кодировка русских букв в операционной системе Microsoft Windows – CP1251 – показана в таблице 7.
Таблица 7. Таблица символов CP1251 (коды с 12810 по 25510)
В операционной системе Linux (как и в большинстве UNIX) для представления русских букв исторически использовалась кодировка КОИ-8R (таблица 8), зарегистрированная в IANA как KOI8-R и описанная в RFC 1489 (см. дополнительную информацию [10]), однако на сегодня большинство дистрибутивов Linux по умолчанию используют кодировку UTF8, о которой будет рассказано ниже.
Таблица 8. Таблица символов KOI8-R (коды с 12810 по 25510)
Стандартизован и зарегистрирован также украинский клон КОИ-8 – KOI8-U (таблица 9), имеющий отличия от KOI8-R во второй строке символов псевдографики. О том, как его утверждали осенью 1997 года, можно узнать из фотографий Тараса Гейченко [11].
Таблица 9. Таблица символов KOI8-U (коды с 12810 по 25510)
Кириллица Macintosh (компьютеров фирмы Apple), она же CP10007, довольно близка к CP1251. Не зарегистрирована в IANA, но часто обозначается как x-mac-cyrillic (таблица 10).
Таблица 10. Macintosh Cyrillic, CP10007 (коды с 12810 по 25510)
Продолжение истории
Развитие обмена текстами через дискеты и модемы (BBS, эхоконференции FidoNet, электронная почта через UUCP) показало недальновидность придуманной ранее схемы. Например, использование одновременно кириллицы и греческих символов в текстах было невозможно, так как они кодировались одними и теми же кодами. Для решения проблемы в 1991 году в Калифорнии была создана некоммерческая организация Unicode Consortium, в которую вошли представители многих зарубежных компьютерных фирм (Borland, IBM, Lotus, Microsoft, Novell, Sun, WordPerfect и др.) и которая занимается развитием и внедрением стандарта The Unicode Standard.
После этого стандарт кодирования символов Unicode становится доминирующим в интернациональных программных многоязычных средах. Microsoft Windows NT и его потомки Windows 2000, 2003, XP, Vista, 7, 8, 8.1 используют Unicode, точнее, UTF-16, как внутреннее представление текста. UNIX-подобные операционные системы типа Linux, BSD и Mac OS X, iOS, Android и др. приняли Unicode (UTF-8) как основное представление многоязычного текста.
Unicode резервирует 1 114 112 (220 + 216) символов кода, в настоящее время используются более 96 000 символов. Первые 256 кодов символов точно соответствуют таковым ISO 8859-1, наиболее популярной восьмиразрядной таблицы символов «западного мира»; в результате первые 128 символов также идентичны таблице ASCII. В таблице 11 показан русский блок Unicode (коды от 040016 до 04FF16).
Таблица 11. Кириллица в Unicode (фрагмент плана 0)
Кодовое пространство стандарта Unicode разделено на 17 планов («planes») от 0 до 16, и каждый план имеет 65 536 (= 216) точек кода. Также планы ещё называют плоскостями.
Первый план (план 0), Основной многоязычный план (BMP – Basic Multilingual Plane) – тот, в котором описано большинство символов. BMP содержит символы почти для всех современных языков и большое количество специальных символов.
Ещё три плана (1, 2, 3) используются для «графических» символов.
План 1. Дополнительный многоязычный план (SMP – Supplementary Multilingual Plane), главным образом используется для исторических символов, а также для музыкальных и математических символов.
План 2. Дополнительный иероглифический план (SIP – Supplementary Ideographic Plane), используется для приблизительно 40 000 редких китайских иероглифов.
План 3. Третичный иероглифический план (TIP – Tertiary Ideographic Plane), используется (зарезервирован) для архаичных китайских иероглифов.
Планы 4 – 13, временно не используются.
План 14. Дополнительный план особого назначения (SSP – Supplementary Special-purpose Plane), отведён для символов, используемых по особому назначению (теги, селекторы написания и др.).
Планы 15 и 16 открыты для любого частного использования.
Однобайтное и многобайтное кодирование, кодировки переменной длины
Для кодирования одного символа может использоваться один или несколько байтов. Если для любого символа достаточного одного байта – кодировка считается однобайтовой, если требуется несколько – многобайтовой. Все существующие текстовые кодировки могут быть классифицированы по данному признаку.
Кодировки переменной длины используют для разных групп символов разную длину. В них одни символы могут быть однобайтовыми, а другие двух-, трёх- и даже четырёхбайтовыми.
Недостатки многобайтовых кодировок
К недостаткам многобайтовых кодировок можно отнести следующее:
1. Излишнюю избыточность (один символ кодируется большим числом битов).
2. Низкую помехоустойчивость (в случае потери одного байта из многобайтового кода все последующие байты смещаются, и весь последующий текст перестаёт правильно читаться).
3. Использование байтов с кодами 0-31 (служебные коды). Подобно двоичным файлам, например, кодировка Unicode мало подходит для непосредственной передачи по сети – байты в тексте вполне могут приходиться на область управляющих символов.
4. Может использоваться разный порядок байт: LITTLE_ENDIAN и BIG_ENDIAN.
Для нивелирования указанных недостатков обычно применяются две другие основанные на Unicode кодировки переменной длины, обозначаемые как UTF (Unicode Transformation Format): семибитная UTF-7 (последний пересмотр – RFC2152, 1997 г., зарегистрирована в IANA как UTF-7) и восьмибитная UTF-8 (RFC 2279, 1998 г., зарегистрирована в IANA как UTF-8).
Замечание. UTF-7 и UTF-8 в каком-то смысле уже не являются языковыми кодировками, а являются программно-распознаваемым кодом относительно исходного Unicode, но зарегистрированы они именно как кодировки, наравне с ISO 8859-5 или KOI8-R.
Естественно, обе не являются специфически «русскими», а пригодны для написания «сколько угодно»-язычного письма.
UTF-8
В UTF-8 [4] все символы разделены на несколько групп по значению первых битов. Символы с кодами менее 12810 кодируются одним байтом, первый бит которого равен нулю, а последующие 7 бит в точности соответствуют 128 символам седьмой таблицы ASCII (см. таблицу 12), следующие 1920 символов – двумя байтами (Greek, Cyrillic, Coptic, Armenian, Hebrew и Arabic-символы). Последующие символы кодируются тремя и четырьмя байтами.
Таблица 12. Принцип кодирования символов в UTF-8
Диапазон кодов (hexadecimal) |
UTF-8 (binary) |
Комментарии |
000000–00007F |
0aaaaaaa |
Первый бит 0, следующие 7 соответствуют таблице ASCII |
000080–0007FF |
110xxxxx 10xxxxxx |
Первые 3 бита 110 – всего используется 2 байта, второй байт начинается с 10 |
000800–00FFFF |
1110xxxx 10xxxxxx 10xxxxxx |
Первые 4 бита 1110 – всего используется 3 байта, второй и третий байты начинаются с 10 |
010000–10FFFF |
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
Первые 5 бит 11110 – всего используется 4 байта, второй, третий и четвёртый байты начинаются с 10 |
Наиболее наглядно правила записи кода одного символа в UTF-8 сформулированы в [6]:
1. Если размер символа в кодировке UTF-8 = 1 байт, то его код имеет вид (0aaa aaaa), где «0» – просто ноль, остальные биты «a» – это код символа в кодировке ASCII.
2. Если размер символа в кодировке в UTF-8 > 1 байт (то есть от 2 до 6):
2.1. Первый байт содержит количество байтов символа, закодированное в единичной системе счисления:
2 — 11
3 — 111
4 — 1111
5 — 1111 1
6 — 1111 11
2.2. Затем следует «0» – бит-терминатор, означающий завершение кода размера.
2.3. Затем идут значащие биты до конца текущего байта.
2.4. Далее идёт один или несколько значащих байтов, которые имеют вид (10xx xxxx), где «10» – биты признака продолжения, а x – значащие биты.
В общем случае варианты представления одного символа в кодировке UTF-8 выглядят так:
(1 байт) 0aaa aaaa
(2 байта) 110x xxxx 10xx xxxx
(3 байта) 1110 xxxx 10xx xxxx 10xx xxxx
(4 байта) 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx
(5 байт) 1111 10xx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx
(6 байт) 1111 110x 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx
Рассмотрим на примере как закодировать русскую букву «а» в UTF-8.
1. Смотрим в таблицу 11 и определяем Unicode код буквы «a» – 043016.
2. Переводим число 043016 в двоичный вид: 0000 0100 0011 0000.
3. Так как русские буквы кодируются двумя символами, то исходя из определения длины кода UTF-8 получаем 11 значащих бит (см. [6]) и выделяем их с конца 0000 0100 0011 0000.
4. Перегруппируем биты из 100 0011 0000 в 10000 110000.
5. Соотнесём данные биты с местом, куда они будут записаны в двухбайтовой записи
110x xxxx 10xx xxxx получим 110x xxxx 10xx xxxx
10000 110000 → 1 0000 11 0000
6. Запишем результат 1101 0000 1011 0000.
7. Переведём в шестнадцатеричный вид, результат готов: D0 B0.
Совершать подобные манипуляции вручную для каждой буквы неудобно, поэтому прибегают к различным упрощающим жизнь таблицам. Зачастую они очень просты, и разъяснять, как ими пользоваться, не имеет смысла. Например, таблица 13 создана Stanislav Borutsky [7].
Таблица 13. Вспомогательный материал для конвертирования символов из одной кодировки в другую
Буква |
CP1251 |
UTF16 |
UTF16 → CP1251 |
UTF8 |
UTF8 → CP1251 |
Ё |
A8 |
04 01 |
byte1==0x04 && byte2==0x01 ? 0xA8 |
D0 81 |
byte1==0xD0 && byte2==0x81 ? 0xA8 |
ё |
B8 |
04 51 |
byte1==0x04 && byte2==0x51 ? 0xB8 |
D1 91 |
byte1==0xD1 && byte2==0x91 ? 0xB8 |
А |
C0 |
04 10 |
byte1 == 0x04 ? byte2 + 0xB0 |
D0 90 |
byte1 == 0xD0 ? byte2 + 0x30 |
Я |
DF |
04 2F |
D0 AF |
а |
E0 |
04 30 |
D0 B0 |
п |
EF |
04 3F |
D0 BF |
р |
F0 |
04 40 |
D1 80 |
byte1 == 0xD1 ? byte2 + 0x70 |
я |
FF |
04 4F |
D1 8F |
Автор таблицы 14 мне неизвестен.
Таблица 14. Вспомогательная таблица для ручного преобразования кодировок символов
***
На данный момент вы получили первичное представление о способах кодирования текстовой информации.
Некоторое количество дополнительной информации и практические задания для самостоятельного выполнения читатели найдут в следующем номере.
- Грошев А. С. Информатика: учеб. для вузов/А. С. Грошев. – Архангельск: Арханг. гос. техн. ун-т, 2010. – 470 с. ISBN 978-5-261-00480-6.
- Закляков П. Представление чисел в памяти ЭВМ. Части 1 и 2. //«Cистемный администратор», 2012 г.: №3, с.90-96; №5, с.88-91; №6, с.84-89; №7-8, с.112-121.
- American National Standards Institute http://www.ansi.org.
- UTF-8, a transformation format of ISO 10646 http://tools.ietf.org/html/rfc2279.
- Internet Assigned Numbers Authority – организация, отвечающая за административное управление в Интернете – http://www.iana.org.
- Примеры ошибок (абракадабра, крякозябры) – http://ru.wikipedia.org/wiki/UTF-8.
- Конвертируем русские буквы из UTF8/UTF16 в CP1251 и обратно – http://cax.livejournal.com/59592.html.
- ISO – http://www.iso.org – International Organization for Standardization; IEC – http://www.iec.ch – International Electrotechnical Commission – ведущие международные организации по стандартизации, в области электротехники – совместные стандарты.
- The International Telecommunication Union http://www.itu.int.
- Дополнительная информация по кодировке KOI8-R – http://koi8.pp.ru.
- Как утверждали кодировку KOI8-U, фотографии с места события – http://www.net.ua/index.php/ru/koi8umenu/12-lavra, 1997 г.
Facebook
Мой мир
Вконтакте
Одноклассники
Google+
|