Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

На главную -> MyLDP -> Электронные книги по ОС Linux
Назад Введение в мир программирования
Глава 2. Архитектура компьютера
Вперед

Глава 3. Представление информации с помощью чисел

В предыдущем разделе мы рассмотрели то, каким образом двоичные числа хранятся в компьютере. Теперь возникает очередной вопрос: Как ЭВМ работают с текстом, графикой и звуком, если всё что они могут хранить в ячейках памяти - это логические нули и логические единицы? Последующие подразделы призваны дать на него ответ.

Кодирование текста

Для описания текста компьютер использует таблицы кодов, где каждому символу (заглавной или строчной букве, знаку препинания, иероглифу) соответствует последовательность из одного или более разрядов числа, записанного в одной из позиционных систем счисления. В таблицы кодов также входят управляющие последовательности (тоже числа в одной из позиционных систем счисления), которые заставляют ЭВМ выполнять некоторые действия (например, подать звуковой сигнал с внутреннего динамика).

Для наглядности скомандуем компьютеру, чтобы он, в ответ на предоставляемое нами число, используя свою таблицу кодов, отправил на стандартное устройство вывода (скорее всего - монитор) печатные знаки и выполнил действие, соответствующее управляющей последовательности.

В целях, обозначенных выше, придумаем небольшой скрипт на языке Bash (см. также варианты решения подобной задачи на других языках программирования).

Создадим пустой файл, запишем туда программу, сохраним изменения в файле и отправим его на исполнение интерпретатору языка Bash. Последовательность символов ``#:'', находящаяся в начале строки, обозначает, что остальной текст в строке является командой среды GNU/Linux. Текст в круглых скобках является комментарием и не должен вводиться пользователем.

#: touch myfile1 (создаём новый файл с именем ``myfile1'')
#: gedit myfile1 (используем текстовый редактор для правки файла ``myfile1''; текстовым редактором может быть
не только gedit, но и Vim, Emacs или любой другой)
#: chmod 0755 myfile1 (изменяем права доступа к файлу ``myfile1'', чтобы находящийся в нём текст
мог быть исполнен интерпретатором языка Bash)
#: ./myfile1 (запускаем, содержащийся в myfile1 скрипт на исполнение)

Вот программа, которую можно записать в myfile1:

echo -e "\x5A";
sleep 2
echo -e "\x07";
sleep 5
echo -e "\x07";
sleep 3
echo -e "\x61";

Результатом исполнения myfile1 (#: ./myfile1) будет появление большой буквы Z на экране монитора, далее, через 2 секунды последует гудок внутреннего динамика вашего персонального компьютера. Пройдёт ещё 5 секунд и динамик прогудит ещё раз. И, наконец, через три секунды, на дисплее появится латинская буква a.

Но какую таблицу кодов использовал компьютер для того, чтобы получить соответствие шестнадцатеричного числа 5A и буквы Z (приставка \x в файлах на языке Bash указывает на то, что следующая за ней последовательность символов является шестнадцатеричным числом)? Это была таблица ASCII (American Standard Code for Information Interchange), которая может входить в состав более крупных таблиц кодов (например, в состав таблиц Unicode).

В Интернет размещено множество публикаций, посвящённых ASCII. Материал, ссылка на который обозначена выше, хорош тем, что приводимая в нём таблица разделена на несколько частей: управляющие последовательности (control characters), печатные символы (printable characters), а также расширенные коды (the extended ASCII codes) для таблицы кодов (кодировки) ISO 8859-1, включающей в себя ASCII как составную часть.

Для представления всех базовых символов (латинского алфавита, знаков препинания и управляющих последовательностей), содержащихся в таблице ASCII, требуется семь двоичных разрядов (7 бит). Добавление восьмого разряда делает таблицу ``расширенной'' и позволяет увеличить количество доступных с её помощью символов. К таким символам могут относиться буквы какого-либо национального алфавита. Например, кодировка ISO 8859-5 разработана как расширение ASCII для оторбражения кириллицы.

Текстовые сообщения операционных систем семейства GNU/Linux сегодня чаще всего кодируются в UTF-8 (Unicode Transformation Format; входит в состав стандарта Юникод --- Unicode). А в русскоязычном сегменте Интернет, на данный момент, особенно распространены веб-страницы в кодировках UTF-8, Windows-1251 (CP-1251) и KOI8-R (Код Обмена Информацией).

Давайте приведём пример одного и того же текста в разных кодировках. Пусть это будет фраза на русском языке: ``Привет, Мир!''.

Каждому символу (даже пробелу между запятой и буквой ``М''), входящему в состав фразы ``Привет, Мир!'' должен соответствовать цифровой код в одной из позиционных систем счисления. Чаще всего для такого кодирования используется шестнадцатеричная система счисления, которая, впрочем, является результатом преобразования двоичных последовательностей в удобный для представления больших чисел вид (один разряд шестнадцатеричной системы счисления может соответствовать числу, для описания которого требуется аж четыре разряда в двоичной системе счисления).

Итак, построим таблицу соответствий каждого из символов текста ``Привет, Мир!'' и его числового представления в кодировках Unicode (форматы UTF-8, UTF-16 и UTF-32), KOI8-R и Windows-1251.

Таблица 1. Соответствия ``символ --- шестнадцатеричное представление'' в разных кодировках.

Символ

Код символа в Unicode

Шестнадцатеричное представление кода в формате UTF-8

Код символа в формате UTF-16BE (Big Endian - старший байт кода символа идёт первым слева)

Код символа в формате UTF-16LE (Little Endian - старший байт кода символа идёт крайним справа)

Код символа в формате UTF-32BE

Код символа в формате UTF-32LE

KOI8-R

CP-1251
(Windows-1251)

П

U+041F

0xD09F

0x041F

0x1F04

0x0000041F

0x1F040000

0xF0

0xCF

р

U+0440

0xD180

0x0440

0x4004

0x00000440

0x40040000

0xD2

0xF0

и

U+0438

0xD0B8

0x0438

0x3804

0x00000438

0x38040000

0xC9

0xE8

в

U+0432

0xD0B2

0x0432

0x3204

0x00000432

0x32040000

0xD7

0xE2

е

U+0435

0xD0B5

0x0435

0x3504

0x00000435

0x35040000

0xC5

0xE5

т

U+0442

0xD182

0x0442

0x4204

0x00000442

0x42040000

0xD4

0xF2

,

U+002C

0x2C

0x002C

0x2C00

0x0000002C

0x2C000000

0x2C

0x2C

 

U+0020

0x20

0x0020

0x2000

0x00000020

0x20000000

0x20

0x20

М

U+041C

0xD09C

0x041C

0x1C04

0x0000041C

0x1C040000

0xED

0xCC

и

U+0438

0xD0B8

0x0438

0x3804

0x00000438

0x38040000

0xC9

0xE8

р

U+0440

0xD180

0x0440

0x4004

0x00000440

0x40040000

0xD2

0xF0

!

U+0021

0x21

0x0021

0x2100

0x00000021

0x21000000

0x21

0x21

В зависимости от того какой формат Unicode выбран, код символа записывается либо в виде одного, двух, трёх или четырёх байтов, содержащих по восемь разрядов (UTF-8); либо в виде одного или двух шестнадцатибитных кодов (UTF-16); либо в виде одного тридцатидвухбитного кода (UTF-32). Подробнее см. ответы на часто задаваемые вопросы о Unicode.

В начале файла в формате UTF-16 иногда находится метка порядка байтов (Byte Order Mark): FFFE --- сигнализирует об обратном порядке следования байтов, то есть Little Endian (например, числовое значение соответствующее букве ``П'' будет записано как 1F04, а не как 041F), FEFF --- сигнализирует о прямом порядке следования байтов, то есть Big Endian.

Давайте теперь проведём эксперимент. Запишем текст в файл, а потом проверим каким образом меняется содержимое файла от того, в какой кодировке находится текст. Запустите интерпретатор команд среды GNU/Linux (например, Bash) и выполните следующую команду.

#: echo Привет, Мир! > test

По этой команде текст ``Привет, Мир!'' в кодировке, используемой в вашей операционной системе по-умолчанию, будет записан в файл с именем test (убедитесь, что до этого в вашем рабочем каталоге не существовало файлов с таким же именем, иначе они будут повреждены, то есть заменены файлом, с одной единственной строкой ``Привет, Мир!'').

Предположим, что основной кодировкой, используемой в нашей операционной системе, является UTF-8. Сделаем несколько копий файла test: одна в кодировке KOI8-R; вторая --- в Windows-1251; третья --- в UTF-16, формируемая программой iconv когда пользователь не указывает порядок байтов; четвёртая --- в UTF-16BE, пятая --- в UTF-16LE; шестая --- в UTF-32, формируемая программой iconv когда пользователь не указывает порядок байтов; седьмая --- в UTF-32BE; восьмая --- в UTF-32LE.

#: cat test | iconv -f UTF-8 -t KOI8-R > test-koi8-r
#: cat test | iconv -f UTF-8 -t Windows-1251 > test-cp-1251

#: cat test | iconv -f UTF-8 -t utf-16 > test-u16
#: cat test | iconv -f UTF-8 -t utf-16BE > test-u16BE
#: cat test | iconv -f UTF-8 -t utf-16LE > test-u16LE

#: cat test | iconv -f UTF-8 -t utf-32 > test-u32
#: cat test | iconv -f UTF-8 -t utf-32BE > test-u32BE
#: cat test | iconv -f UTF-8 -t utf-32LE > test-u32LE

Итак, у нас получилось девять файлов: test, test-koi8-r, test-cp-1251, test-u16, test-u16BE, test-u16LE, test-u32, test-u32BE, test-u32LE. Они содержат в себе одинаковый текст, но в разных кодировках. Можно ли сравнить содержимое этих файлов? Обратимся за помощью к программе diff и поищем отличия между содержимым test и test-koi8-r.

#: diff test test-koi8-r

diff сообщает о том, что файлы отличаются друг от друга. Напомним, что операционная система, в который мы проводим сравнение файлов, использует UTF-8 как кодировку по-умолчанию.

1c1
< Привет, Мир!
---
> Ŕ, !

Теперь мы на практике убедились, что если записать два одинаковых текстовых сообщения в разных кодировках, они почти наверняка окажутся для компьютера неэквивалентными! Почему ``почти наверняка''? Мы исходим из предположения о том, что одинаковые текстовые сообщения написаны с использованием кириллицы (или любого другого алфавита отличного от латиницы, не содержащей модифицированных букв). В частности, в рассмотренном выше примере проверялось содержание файлов с текстом на русском языке. Буквы латинского алфавита в современных вычислительных системах в абсолютном большинстве случаев кодируются на основе стандарта ASCII (о нём говорилось выше) и поэтому если по аналогии с представленным ранее примером создать файлы в разных кодировках, но уже с текстом ``Hello, World!'', программа diff не сможет найти отличий между содержимым некоторых из этих файлов (test, test-koi8-r, test-cp-1251). Даже программа md5sum вычислит одинаковые контрольные суммы для test, test-koi8-r и test-cp-1251. Если же мы попробуем посчитать контрольные суммы для файлов, содержащих сообщения на русском языке, получим следующий результат.

#: md5sum test
964b0a427bffc92cba443ed6be9fd824  test

#: md5sum test-koi8-r
f0099e08925bf4905b89145461139b07  test-koi8-r

#: md5sum test-cp-1251
c869b00301492f7cac4ed8255efa11d1  test-cp-1251

#: md5sum test-u16
256fd99a15619dd240bda35298e5d855  test-u16

#: md5sum test-u16BE
862c7ae4d24aa76545a56d1a70f4ffab  test-u16BE

#: md5sum test-u16LE
466800003cb011dea942da6362d7bd85  test-u16LE

#: md5sum test-u32
c6b39802702df2b0e11afeffae0205e7  test-u32

#: md5sum test-u32BE
e34bbd6b32bdf84d84745bc5cd545bd6  test-u32BE

#: md5sum test-u32LE
9423d15cf69eea09d47bb58eeec0e517  test-u32LE

Важно отметить, что особенности работы программы iconv являются причиной того, что файлы test-u16 и test-u16LE отличаются друг от друга только наличием метки порядка байтов в начале файла (то же справедливо для пары test-u32 и test-u32LE).

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

#: xxd test
0000000: d09f d180 d0b8 d0b2 d0b5 d182 2c20 d09c  ............, ..
0000010: d0b8 d180 210a                           ....!.

#: xxd test-koi8-r
0000000: f0d2 c9d7 c5d4 2c20 edc9 d221 0a         ......, ...!.

#: xxd test-cp-1251
0000000: cff0 e8e2 e5f2 2c20 cce8 f021 0a         ......, ...!.

#: xxd test-u16
0000000: fffe 1f04 4004 3804 3204 3504 4204 2c00  ....@.8.2.5.B.,.
0000010: 2000 1c04 3804 4004 2100 0a00             ...8.@.!...

#: xxd test-u16BE
0000000: 041f 0440 0438 0432 0435 0442 002c 0020  ...@.8.2.5.B.,.
0000010: 041c 0438 0440 0021 000a                 ...8.@.!..

#: xxd test-u16LE
0000000: 1f04 4004 3804 3204 3504 4204 2c00 2000  ..@.8.2.5.B.,. .
0000010: 1c04 3804 4004 2100 0a00                 ..8.@.!...

#: xxd test-u32
0000000: fffe 0000 1f04 0000 4004 0000 3804 0000  ........@...8...
0000010: 3204 0000 3504 0000 4204 0000 2c00 0000  2...5...B...,...
0000020: 2000 0000 1c04 0000 3804 0000 4004 0000   .......8...@...
0000030: 2100 0000 0a00 0000                      !.......

#: xxd test-u32BE
0000000: 0000 041f 0000 0440 0000 0438 0000 0432  .......@...8...2
0000010: 0000 0435 0000 0442 0000 002c 0000 0020  ...5...B...,...
0000020: 0000 041c 0000 0438 0000 0440 0000 0021  .......8...@...!
0000030: 0000 000a                                ....

#: xxd test-u32LE
0000000: 1f04 0000 4004 0000 3804 0000 3204 0000  ....@...8...2...
0000010: 3504 0000 4204 0000 2c00 0000 2000 0000  5...B...,... ...
0000020: 1c04 0000 3804 0000 4004 0000 2100 0000  ....8...@...!...
0000030: 0a00 0000                                ....

Также приведём вывод xxd в двоичной форме (крайняя колонка слева содержит шестнадцатеричный адрес байта относительно начала файла).

#: xxd -b -c 1 test
0000000: 11010000  .
0000001: 10011111  .
0000002: 11010001  .
0000003: 10000000  .
0000004: 11010000  .
0000005: 10111000  .
0000006: 11010000  .
0000007: 10110010  .
0000008: 11010000  .
0000009: 10110101  .
000000a: 11010001  .
000000b: 10000010  .
000000c: 00101100  ,
000000d: 00100000
000000e: 11010000  .
000000f: 10011100  .
0000010: 11010000  .
0000011: 10111000  .
0000012: 11010001  .
0000013: 10000000  .
0000014: 00100001  !
0000015: 00001010  .

#: xxd -b -c 1 test-koi8-r
0000000: 11110000  .
0000001: 11010010  .
0000002: 11001001  .
0000003: 11010111  .
0000004: 11000101  .
0000005: 11010100  .
0000006: 00101100  ,
0000007: 00100000
0000008: 11101101  .
0000009: 11001001  .
000000a: 11010010  .
000000b: 00100001  !
000000c: 00001010  .

#: xxd -b -c 1 test-cp-1251
0000000: 11001111  .
0000001: 11110000  .
0000002: 11101000  .
0000003: 11100010  .
0000004: 11100101  .
0000005: 11110010  .
0000006: 00101100  ,
0000007: 00100000
0000008: 11001100  .
0000009: 11101000  .
000000a: 11110000  .
000000b: 00100001  !
000000c: 00001010  .

Проанализируем полученный результат. Из документации известны следующие положения.

Во-первых, формат UTF-8 (используется для записи кириллических букв в файле test) выделяет по два байта на хранение каждой буквы кириллицы. Кодировки KOI8-R (test-koi8-r) и Windows-1251 (test-cp-1251) выделяют по одному байту на один кириллический символ. UTF-16 (и big endian и little endian) выделяет по два байта на один кириллический символ. UTF-32 (и big endian и little endian) выделяет по четыре байта на один кириллический символ.

Во-вторых, кодовая таблица ASCII включена в состав UTF-8, KOI8-R, Windows-1251, UTF-16 и UTF-32 для представления латинских букв (без модификаций, к которым, например, можно отнести добавление к букве разнообразных диакритических знаков), знаков препинания и управляющих последовательностей (например, знака перевода строки --- line feed, которому соответствует шестнадцатеричное число 0A).

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

Благодаря отмеченным особенностям кодирования, шестнадцатеричное представление каждого символа текста ``Привет, Мир!'' может быть легко найдено в созданных нами файлах. С этой целью удобно использовать таблицу соответствий ``символ --- шестнадцатеричное представление'', приведённую ранее.

Теперь понятно почему программа md5sum генерировала разные контрольные суммы для всех рассмотренных файлов (test, test-koi8-r, test-cp-1251, test-u16, test-u16BE, test-u16LE, test-u32, test-u32BE, test-u32LE) --- эти файлы содержат разные последовательности чисел!

Таким образом, если программист не предусмотрел возможности работы с текстом, находящимся в разных кодировках, его программа просто не будет знать, что ей делать с числами, соответствующими символам кириллицы (или любого другого алфавита). Например, xxd не умеет выводить текст на русском языке в формате UTF-8 и поэтому вместо кириллических букв она печатает точки (см. ранее). А вот с текстом в кодировке ASCII она (программа xxd) справляется легко:

#: echo Hello, World! > ascii-text
#: xxd -c 1 ascii-text
0000000: 48  H
0000001: 65  e
0000002: 6c  l
0000003: 6c  l
0000004: 6f  o
0000005: 2c  ,
0000006: 20
0000007: 57  W
0000008: 6f  o
0000009: 72  r
000000a: 6c  l
000000b: 64  d
000000c: 21  !
000000d: 0a  .

Возникает вопрос: С какими кодировками должны уметь работать наши программы? Здесь всё зависит от целей, которые мы перед собой ставим. Если речь идёт о попытке заработать деньги на программе, то она должна поддерживать работу с кодировками, которыми пользуются её потенциальные покупатели и пользователи. В общем случае, разумнее всего научить программу понимать Unicode (UTF-8), KOI8-R и Windows-1251 (UTF-16 пригодится для программ, работающих с иероглифами).

Unicode является наиболее перспективной из современных систем кодирования текста. Во-первых, она подробно документирована и активно поддерживается крупными организациями и фирмами. Во-вторых, с её помощью можно работать с большим количеством национальных алфавитов (однобайтовые кодировки, например, KOI8-R или Windows-1251 поддерживают только латинские буквы и кириллицу).

Велика вероятность, что Вам, уважаемый читатель, часто придётся иметь дело с Unicode, поэтому остановимся подробнее на том, по каким принципам этот стандарт предлагает преобразовывать числа в текст и наоборот.

Стандарт Unicode представляет из себя систему кодирования символов, предназначенную для применения в процессе взаимодействия людей, являющихся носителями разных языков. Также в Unicode учитываются потребности пользователей, имеющих дело с текстами, содержащими редко встречающиеся печатные знаки. По большому счёту этот стандарт призван помочь реализовать унифицированный подход к обработке текстовой информации в вычислительных системах и сетях всех уровней (от локального до глобального).

Для того, чтобы охватить абсолютное большинство из известных знаковых систем и при этом быть технически удобным стандартом, который выгодно использовать, Unicode строится на достаточно оригинальном подходе к представлению текста в числовой форме. Каждому символу, кодируемому согласно правил Unicode, соответствует уникальное числовое значение, особым образом интерпретируемое программами, поддерживающими этот стандарт. Пространство для этих значений включает числа (коды) от 0 до 10FFFF16 и делится на 17 групп (planes). Значения от U+0000 до U+FFFF относятся к первой --- базовой многоязыковой группе (Basic Multilingual Plane), которая, в частности, включает кириллицу, латинский и греческий алфавиты; значения от U+10000 до U+1FFFF относятся ко второй --- дополнительной многоязыковой группе от U+20000 до U+2FFFD (Supplementary Multilingual Plane), в которую, например, входят египетские иероглифы; третья группа --- дополнительная группа для идеографических видов письменности (Supplementary Ideographic Plane) от U+30000 до U+3FFFD, включающая, например, китайские иероглифы. Группы с четвёртой по тринадцатую включительно (от U+30000 до U+DFFFF), на момент написания этих строк, не содержат кодов символов и служат в качестве резерва для хранения информации об идеографических видах письменности ещё не включённых в состав Unicode. Четырнадцатая группа (от U+E0000 до U+E0FFF) включает коды неотображаемых графически символов форматирования текста (согласно версии 6.0 стандарта Unicode к данному типу относятся также подгруппы U+2060...U+206F, U+FFF0...U+FFF8; подробнее см. [Unicode-6.0.0, p. 143-144]). В пятнадцатую и шестнадцатую группы входят коды (от U+E000 до U+F8FF, от U+F0000 до U+FFFFD, от U+100000 до U+10FFFD) для частного использования (Private Use Area), которые могут быть ассоциированы с произвольным набором символов.

Символы, имеющие отношение к кириллице размещены в первой группе кодов (Basic Multilingual Plane) стандарта Unicode по адресам от U+0400 до U+04FF (Cyrillic); от U+0500 до U+052F (Cyrillic Supplement) от U+2DE0 до U+2DFF (Cyrillic Extended-A); от U+A640 до U+A69F (Cyrillic Extended-B). Некоторую ценную информацию по поводу того, какие символы входят в каждую из перечисленных выше подгрупп, можно найти в статье ``Кириллица в Юникоде'', опубликованной в рамках проекта Wikipedia.

Коды символов, размещённые в таблицах соответствий, публикуемых на официальном сайте проекта Unicode, отличаются от тех числовых последовательностей, которые можно увидеть если просматривать файл, закодированный в соответствиие с UTF-8 в hex-редакторе. Почему так происходит? Ранее мы создали файл test, в который была записана фраза ``Привет, Мир!''. Если внимательно посмотреть на результат работы программы xxd (см. выше), мы действительно заметим, что, например, буква ``П'' интерпретируется как шестнадцатеричное число D09F. Но ведь в стандарте Unicode эта буква имеет код U+041F!? Всё дело в том, что операционная система, в которой мы создали файл test настроена таким образом, что по-умолчанию использует формат записи UTF-8 (наряду с UTF-16 и UTF-32 является одним из форматов записи символов в Unicode), прокомментированный в документе RFC 3629.

Код символа в UCS (Universal Character Set --- Универсальная кодировка символов, определяемая стандартом Unicode) может содержать от четырёх (например, U+041F) до шести (например, U+100000) шестнадцатеричных цифр. Символы с кодами от U+0000 до U+10FFFF в UTF-8 могут быть записаны с использованием от одного до четырёх октетов (чисел, содержащих 8 двоичных разрядов). Старший бит первого октета (если для кодирования символа нужен только один октет) всегда равен нулю, а остальные его семь бит применяются для записи числа, соответствующего кодируемому символу. Старший бит всех октетов кроме первого всегда равен единице. Второй бит всех октетов кроме первого всегда равен нулю. В результате, двоичные числа для записи кодов символов в формате UTF-8 выглядят следующим образом.

Таблица 2. Формат записи UTF-8

Октет 1

Октет 2

Октет 3

Октет 4

0xxxxxxx

110xxxxx

10xxxxxx

1110xxxx

10xxxxxx

10xxxxxx

11110xxx

10xxxxxx

10xxxxxx

10xxxxxx

Как видно, формат UTF-8 позволяет использовать до двадцати одного двоичного разряда для записи кодов символов (посчитайте количество ``иксов'' в числе, содержащем четыре октета). Заметно также, что первый октет кода символа в формате UTF-8 указывает на общее количество октетов в коде символа.

Итак, если взять шестнадцатеричный код буквы ``П'' (041F) и записать его как двоичное число справа-налево в формате UTF-8, мы получим: 11001000010011111 (как отмечалось ранее, двоичные разряды, выделенные жирным шрифтом, всегда присутствуют в двухоктетном числе в формате записи UTF-8).

Если мы запишем представление буквы ``П'' в формате UTF-8 в файл, то открыв это файл с помощью программы xxd, мы получим строку: 0000000: d09f 0a ..., где шестнадцатеричное число D09F будет соответствовать записи 11001000010011111. Таким образом, код символа в формате UTF-8 формируется по определённым правилам (см. выше) и отличается от шестнадцатеричного числа, непосредственно хранящегося в файле. Числа, непосредственно хранящиеся в текстовом файле (в формате UTF-8) записаны в третьем столбце Таблицы 1 (приставка 0x указывает на то, что эти числа записаны в шестнадцатеричной форме).

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

Таблица 3. Код символа в формате UTF-8 --- Количество используемых октетов

Код символа

Количество октетов

от 0000 0000 до 0000 007F

  1

от 0000 0080 до 0000 07FF

  2

от 0000 0800 до 0000 FFFF

  3

от 0001 0000 до 0010 FFFF

  4

Информация о формате UTF-16 размещена в RFC 2781. Обычно этот формат применяется совместно с UTF-32 для того, чтобы с одной стороны --- иметь возможность представлять числовое значение, соответствующее символу без необходимости дополнительных преобразований (достоинство UTF-32), а с другой стороны --- экономить вычислительные мощности ЭВМ (достоинство UTF-16 в сравнении с UTF-32).

Кодировку символов можно представить в виде четырёхуровневой модели (подробнее см. [Constable2001], [WistlerDavisFreytag2008]).

  • Уровень 1. Неупорядоченный набор символов, который нужно закодировать (Abstract Character Repertoire --- ACR).
  • Уровень 2. Таблица соответствий между символами, которые нужно закодировать и неотрицательными целыми числами (Coded Character Set --- CCS).
  • Уровень 3. Таблица соответствий между неотрицательными целыми числами и последовательностями кодов фиксированного или переменного размера (Character Encoding Form --- CEF).
  • Уровень 4. Набор обратимых преобразований кодов (эти коды были получены на третьем уровне модели) в последовательности байтов (Character Encoding Scheme --- CES).

Литература для самообразования

  1. KOI8-C: расширение кодировки KOI8-R. URL: http://oldrus-ispell.sourceforge.net/koi8-extended.html (дата обращения: 16.02.2012).
  2. Таненбаум Э. Архитектура компьютера. 5-е изд. СПб.: Питер, 2007. С. 89-91
  3. Что такое Unicode? URL: http://www.unicode.org/standard/translations/russian.html (дата обращения: 06.02.2012).
  4. ASCII Code - The extended ASCII table. URL: http://www.ascii-code.com/ (дата обращения: 24.01.2012).
  5. Constable P. Character set encoding basics. Understanding character set encodings and legacy encodings. URL: http://scripts.sil.org/IWS-Chapter03 (дата обращения: 24.01.2012).
  6. Dürst M. J., Yergeau F., Ishida R., Wolf M., Texin T. Character Model for the World Wide Web 1.0: Fundamentals. URL: http://www.w3.org/TR/charmod/ (дата обращения: 04.02.2012).
  7. Jennings T. An annotated history of some character codes or ASCII: American Standard Code for Information Infiltration. URL: http://www.wps.com/projects/codes/ (дата обращения: 23.01.2012).
  8. Kuhn M. UTF-8 and Unicode FAQ for Unix/Linux. URL: http://www.cl.cam.ac.uk/~mgk25/unicode.html (дата обращения: 24.01.2012).
  9. Terminal control/Ringing the terminal bell. URL: http://rosettacode.org/wiki/Terminal_control/Ringing_the_terminal_bell (дата обращения: 24.01.2012).
  10. The Linux Cyrillic HOWTO (текст на русском языке). URL: http://www.opennet.ru/docs/HOWTO-RU/Cyrillic-HOWTO.html (дата обращения: 24.01.2012).
  11. Whistler K., Davis M., Freytag A. Unicode Technical Report #17. Unicode Character Encoding Model. URL: http://unicode.org/reports/tr17/ (дата обращения: 04.02.2012).
  12. Yergeau F. UTF-8, a transformation format of ISO 10646. URL: https://tools.ietf.org/html/rfc3629 (дата обращения: 13.02.2012).

Предыдущий раздел: Оглавление Следующий раздел:
Логика работы с памятью. Машинный язык. Режимы адресации   Ввод текста. Взаимодействие с клавиатурой