О кодировках и кодовых страницах

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

Начну с небольшого экскурса в историю компьютера. Поскольку компьютер использовался для обработки информации, то он просто обязан представлять эту информацию в «человеческом» виде. Компьютер хранит информацию в виде чисел (байтов), а человек воспринимает символы (буквы, цифры, различные знаки). Значит, надо сделать сопоставление число <-> символ и задача будет решена. Сначала посчитаем, сколько символов нам надо (не забудем, что «мы» — американцы, использующие латинский алфавит). Нам надо 10 цифр + 26 заглавных букв английского алфавита + 26 строчных букв + математические знаки (хотя бы +-/*=><%) + знаки препинания (.,!?:;’” ) + различные скобки + служебные символы (_^%$@|) + 32 непечатных управляющих символов для работы с устройствами (в первую очередь, с телетайпом). В общем, 128 символов хватает «впритык» и этот стандартный набор символов «мы» назвали ASCII, т.е. «American Standard Code for Information Interchange»

Отлично, для 128 символов достаточно 7 бит. С другой стороны, в байте 8 бит и каналы связи 8-битные (забудем про «доисторические» времена, когда в байте и каналах бит было меньше). По 8-ми битному каналу будем передавать 7 бит кода символа и 1 бит контрольный (для повышения надежности и распознавания ошибок). И все было замечательно, пока компьютеры не стали использоваться в других странах (где латиница содержит больше 26 символов или вообще используется не латинский алфавит). Вместо того, чтобы всем поголовно освоить английский, жители СССР, Франции, Германии, Грузии и десятков других стран захотели, чтобы компьютер общался с ними на их родном языке. Пути были разные (в зависимости от остроты проблемы): одно дело, если к 26 символам латиницы надо добавить 2-3 национальных символа (можно пожертвовать какими-то специальными) и другое дело, когда надо «вклинить» кириллицу. Теперь «мы» — русские, стремящиеся «русифицировать» технику. Первыми были решения на основе замены строчных английских букв прописными русскими. Однако проблема в том, что русских букв (33) и они не влезают на 26 мест. Надо «уплотнить» и первой жертвой этого уплотнения пала буква Ё (еe просто повсеместно заменили на Е). Другой прием – вместо «русских» A,E,K,M,H,O,P,C,T стали использовать похожие английские (таких букв даже больше чем надо, но в некоторых парах прописные похожие, а строчные — не очень: Hh Tt Bb Kk Mm). Но все же «вклинили » и в результате весь вывод шел ПРОПИСНЫМИ БУКВАМИ, что неудобно и некрасиво, однако со временем привыкли. Второй прием – «переключение языка». Код русского символа совпадал с кодом английского символа, но устройство помнило, что сейчас оно в русском режиме и выводило символ кириллицы (а в английском режиме – латиницы). Режим переключался двумя служебными символами: Shift Out (SO, код 14) на русский и Shift IN (SI, код 15) на английский (интересно, что когда-то в печатных машинках использовалась двухцветная лента и SO приводил к физическому подъему ленты и в результате печать шла красным, а SI ставил ленту на место и печать снова шла черным). Текст с большими и маленькими буквами стал выглядеть вполне прилично. Все эти варианты более-менее работали на больших компьютерах, но после выпуска IBM PC началось массовое распространение персональных компьютеров по всему миру и надо было что-то решать централизовано.

Решением стала разработанная фирмой IBM технология кодовых страниц. К этому времени «контрольный символ» при передаче потерял свою актуальность и все 8-бит можно было использовать для кода символа. Вместо диапазона кодов 0-127 стал доступен диапазон 0-255. Кодовая страница (или кодировка)– это сопоставление кода из диапазона 0-255 некоему графическому образу (например, букве «Я» кириллицы или букве «омега» греческого). Нельзя сказать «символ с кодом 211 выглядит так», но можно сказать «символ с кодом 211 в кодовой странице CP1251 выглядит так: У, а в CP1253(греческая) выглядит так: Σ ». Во всех (или почти всех) кодовых таблица первые 128 кодов соответствуют таблице ASCII, только для первых 32 непечатных кодов IBM «назначила» свои картинки (которые показывается при выводе на экран монитора). В верхней части IBM разместила символы псевдографики (для рисования различных рамок), дополнительные символы латиницы, используемые в странах Западной Европы, некоторые математические символы и отдельные символы греческого алфавита. Эта кодовая страница получила название CP437 (IBM разработала и множество других кодовых страниц) и по умолчанию использовалась в видеоадаптерах. Кроме того, различные центры стандартизации (мировые и национальные) создали кодовые страницы для отображения национальных символов. Наши компьютерные «умы» предложили 2 варианта: основная кодировка ДОС и альтернативная кодировка ДОС. Основная предназначалась для работы везде, а альтернативная — в особых случаях, когда использование основной неудобно. Оказалось, что таких особых случаев большинство и основной (не по названию, а по использованию) стала именно «альтернативная» кодировка. Думаю, такой исход был ясен с самого начала для большинства специалистов (кроме «ученых мужей», оторванных от жизни). Дело в том, что в большинстве случаев использовались английские программы, которые «для красоты» активно использовали псевдографику для рисования различных рамок и тп. Типичные пример — суперпопулярный Нортон коммандер, стоящий тогда на большинстве компьютеров. Основная кодировка на местах псевдографики разместила русские символы и панели нортона выглядели просто ужасно (равно как и любой другой псевдографический вывод). А альтернативная кодировка бережно сохранила символы пседографики, использую для русских букв другие места. В результате и с Нортон коммандером и с другими программами вполне можно было работать. Андрей Чернов (широко известная личность в то время) разработал кодировку KOI8-R (КОИ8), пришедшую с «больших» компьютеров, где господствовал UNIX. Ее особенностью было то, что если у русского символа пропадал 8-й бит, то получившийся в результате «обрезания» английский символ будет созвучен исходному русскому. И вместо «Привет» получался «pRIVET», что не совсем то, но хотя бы читаемо. В результате в СССР на компьютерах использовали 3 различных кодовых страницы (основную, альтернативную и KOI8). И это не считая различных «вариаций», когда в альтернативной кодировке, скажем, отдельные символы (а то и строки) изменялись. От KOI8 тоже «отпочковывались» варианты — украинский, белорусский, таджикский, кавказский и др. Оборудование (принтеры, видеодаптеры) тоже надо было настраивать (или «прошивать») для работы со своими кодировками. Коммерсанты могли привезти дешевую партию принтеров (из эмиратов, например, по бартеру) а они не работали с русскими кодировками.

Тем не менее в целом кодовые страницы позволили решить проблему вывода национальных символов (устройство просто должно уметь работать с соответствующей кодовой страницей), но породили проблему множественности кодировок, когда почтовая программа отправляет данные в одной кодировке, а принимающая программа показывает их в другой. В результате пользователь видит так называемые «кракозябры» (вместо «привет» написано "ЏаЁўҐв" или «оПХБЕР»). Потребовались программы-перекодировщики, переводящие данные из одной кодировки в другую. Увы, порой письма при прохождении через почтовые серверы неоднократно автоматически перекодировались (или даже «обрезался» 8-й бит) и нужно было найти и выполнить всю цепочку обратных преобразований.

После массового перехода на Windows к трем кодовым страницам добавилась четвертая (Windows-1251 она же CP1251 она же ANSI ) и пятая (CP866 она же OEM или DOS). Не удивляйтесь — Windows для работы с кириллицей в консоли по-умолчанию использует кодировку CP866 (русские символы такие же как в «альтернативной кодировке», только некоторые спецсимволы отличаются), для других целей — кодировку CP1251. Почему Windows понадобилось две кодировки, неужели нельзя было обойтись одной? Увы, не получается: DOS-кодировка используется в именах файлов (тяжелое наследие DOS) и консольные команды типа dir, copy должны правильно показывать и правильно обрабатывать досовские имена файлов. С другой стороны, в этой кодировке много кодов отведено символам псевдографики (различным рамкам и т.п.), а Windows работает в графическом режиме и ей (а точнее, windows-приложениям) не нужны символы псевдографики (но нужны занятые ими коды, которые в CP1251 использованы для других полезных символов). Пять кириллических кодировок поначалу еще больше усугубили ситуацию, но со временем наиболее популярными стали Windows-1251 и KOI8, а досовскими просто стали меньше пользоваться. Еще при использовании Windows стало неважно, какая кодировка в видеоадаптере (только изредка, до загрузки Windows в диагностических сообщениях можно видеть «кракозябры»).

Решение проблемы кодировок пришло, когда повсеместно стала внедряться система Unicode (и для персональных ОС и для серверов). Unicode каждому национальному символу ставит в соответствие раз и навсегда закрепленное за ним 20-ти битовое число («точку» в кодовом пространстве Unicode, причем чаще всего хватает 16 бит, поскольку 20-битные коды используются для редких символов и иероглифов), поэтому нет необходимости перекодировать (подробнее об Unicode см следующую запись в журнале). Теперь для любой пары <код байта>+<кодовая страница> можно определить соответствующий ей код в Unicode (сейчас в кодовых страницах для каждого 8-битного кода показывается 16-битный код Unicode) и потом при необходимости вывести этот символ для любой кодовой страницы, где он присутствует. В настоящее время проблема кодировок и перекодировок для пользователей практически исчезла, но все же изредка приходят письма, где либо тема письма либо содержание «не в той» кодировке.

Интересно, что примерно год назад проблема кодировок ненадолго всплыла при «наезде» ФАС на сотовых операторов, мол те дискриминируют русскоязычных пользователей, поскольку за передачу кириллицы берут больше. Это объясняется техническим решением, выбранным разработчиком протокола SMS связи. Если бы его россияне разработали, они бы, возможно, отдали приоритет кириллице. В указанной статье «начальник управления контроля транспорта и связи Дмитрий Рутенберг отметил, что существуют и восьмибитные кодировки для кириллицы, которые могли бы использовать операторы.» Во как — на улице 21-й век, Unicode шагает по миру, а господин Рутенберг тянет нас в начало 90-х, когда шла «война кодировок» и проблема перекодировок стояла во весь рост. Интересно, в какой кодировке должен получить СМС Вася Пупкин, пользующийся финским телефоном, находящийся в Турции на отдыхе, от жены с корейским телефоном, отправляющей СМС из Казахстана? А от своего французского компаньона (с японским телефоном), находящегося в Испании? Думаю, никакой начальник ответа на этот вопрос дать не сможет. К счастью, это «экономное» предложение не воплотилось в жизнь.

Юный читатель может спросить — а что помешало сразу использовать Unicode, зачем были придуманы эти заморочки с кодовыми страницами? Думаю, дело в финансовой стороне проблемы. Unicode требует в 2 раза больше памяти, а память стоит денег (и дисковая и ОЗУ). Стал бы американец покупать компьютер на 1-2 тыс дороже из-за того, что «теперь новая ОС требует больше памяти, но позволяет без проблем работать с русским, европейскими, арабскими языками»? Боюсь, простой англоязычный покупатель воспринял бы такой аргумент «неадекватно» (и обратился бы к другим производителям).
Поделиться публикацией
Комментарии 23
    0
    Думаю, дело в финансовой стороне проблемы. Unicode требует в 2 раза больше памяти, а память стоит денег (и дисковая и ОЗУ)

    Тут зависит от типа Unicode кодировки. UTF-8 совместима с 7ми битными символами, а остальные могут занимать от 2 до 6 байт(используется правда только до 4х).
    Тут ИМХО больше дело с сложности обработки, да и возможно не думали обо всё этом когда первые компьютеры/OS делали. А вот когда это по миру расползаться начало вот тут и возникли проблемы.
      0
      А разве кириллические символы в UTF-8 не по два байта занимают? Возможно, для некоторых языков могла получиться экономия, но, действительно, повышенная сложность алгоритмов ее нивелировала бы. Те же «простые англоязычные читатели» не поймут — для них не изменится память, но изменятся прошивки всех телефонов.
        0
        В UTF-8 кириллица занимает 2 байта, откуда взялось сомнение?
          0
          Юношеский склероз-с…
      +10
      Unicode <...> поэтому нет необходимости перекодировать
      почему это нету? юникод это просто [виртуальная] таблица символов, в компьютере остаются тоже «кодировки» (utf-8 или там utf-16, например).
      (подробнее об Unicode см следующую запись в журнале)
      ой, как неловко спалился кросспостинг)
        0
        А вот меня давно мучает такой ламерский вопросик) Извиняюсь, если немного не в тему.
        Храню матричный принтер 1994 года Epson LX1050+, рабочий. Есть комп с XP и LPT-портом.
        Принтер с этого компьютера печатает только в графическом режиме. А можно ли заставить его печатать из-под windows именно в текстовом, не загружаясь в DOS?
          +2
          Думаю можно если печатать «мимо» драйвера, то есть открыть LPT порт и слать туда текст+управляющие символы.
            0
            Именно так, см его встроенные шрифты, и команды всякие esc/pos, табуляторы и прочее… Там весьма хитро все накручено… Я так со старым HP баловался… тумблерами набирая байты!
            0
            echo «Hello world!» > lpt1
              +1
              Стандарт EPSON ESC/P вам в помощь. Ну и прямой доступ к lpt обязательно потребуется. Кстати, в режиме 9pin (как правило это нулевой шрифт в памяти) ваш матричник будет фигачить с первой комической скоростью, чего нельзя сказать о «красивых» вшитых шрифтах (всякие Sans и Times ) — на них производительность падает ниже плинтуса.
              0
              Ее особенностью было то, что если у русского символа пропадал 8-й бит, то получившийся в результате «обрезания» английский символ будет созвучен исходному русскому

              Этот трюк КОИ-8 позаимствовала из 5-битного телеграфного кода МТК-2.

              Мне тут недавно пришло письмо в семибитном US-ASCII с обрезанным 8-м битом. К сожалению, исходная кодировка была Windows-1251, и все русские буквы превратились в тыкву — стали совершенно нечитаемы. Адресат уже ушел домой, и пришлось писать скрипт для восстановления бита (-:
                0
                Можно обойтись и без скрипта :)

                $ echo ophber | iconv -f koi-7 -t koi-8 | iconv -f cp1251
                привет
                  0
                  C KOI7/8 дело имел, читал статьи Чижова, а про МТК-2, к сожалению, не слышал. Возможно, он «дедушка» семейства KOI… Спасибо.
                  0
                  Во как — на улице 21-й век, Unicode шагает по миру,
                  а кто-то всерьёз задумывается о судьбе самого дорогого способа передачи 140 байт.
                    +1
                    ASCII вообще-то появился еще в 60-х и был предназначен для телетайпа. Отсюда такие экзотические кода как раздельные CR и LF — первый смещает каретку к началу строки, а второй прокручивает бумагу на одну строчку вниз, это совершенно логично на механической печатной машинке. Еще пример — Rubout (127), поскольку стереть символ с бумаги невозможно, его при необходимости просто забивали черным квадратиком. Из 32 управляюших символов сейчас используется только четыре, остальные были нужны именно для телетайпа с механической клавиатурой. Оттуда же кстати контроль четности по 8-му биту, видимо помехи на линии были серьезной проблемой.
                      +4
                      Мне изложение этого материала показалось очень странным, потому что с одной стороны, он претендует на ретроспективу, то есть на обзор исторического развития ситуации, а с другой — повествование часто перескакивает с одного на другое. И это не единственная проблема.

                      Например, вполне можно было упомянуть, что набор символов ASCII изначально не имел никакого отношения к компьютерам, потому что был разработан (аж в 1963 году) для передачи телеграфных (точнее — телетайпных) сообщений. Именно потому, кроме собственно символов, эта кодировка (и ее последующие реинкарнации) содержала управляющие коды, служившие сначала командами для механики телетайпов, а потом — для управления курсором текстового дисплея.

                      Кроме того, в тексте не до конца однозначно прояснен вопрос с различиями между кодовыми страницами (code page), наборами символов (character set) и кодировками (encoding). Набор символов — это просто символы, без указания того, как их следует хранить. Кодовая страница — это таблица соответствия набора символов, их кодов и способа хранения этих кодов. А кодировка — это, строго говоря, способ хранения этих кодов сам по себе.
                      Так например, набор символов Unicode может быть записан в кодовой странице 65001 (по версии Microsoft) с использованием кодировки UTF-8.

                      Ну и последний «детский» вопрос о том, почему сразу не использовать Unicode, весьма странен, как и ответ на него. В шестидесятых годах не было никакого Unicode, а идея об общем наборе символов получила первую практическую реализацию только в конце восьмидесятых, став официальным стандартом только в 1991-м. Невозможно использовать то, чего нет.
                      Кроме того, нельзя забывать о серьезном «телеграфном наследии» компьютеров, использовавших текстовый режим и о том, что многоязычность и по сей день не так уж и востребована в общем случае, так что в том, чтобы на дисплее (и на принтерах, которые тоже весьма долго были, главным образом, текстовыми) сразу отображались символы на многих языках, практической нужды не было, а сделать эту возможность «довеском» было бы, действительно, слишком дорого.
                        0
                        Спасибо все читателям за проявленный интерес (на LiveJournal статья пролежала 3 года практически без откликов). Я хотел написать не научный трактат, а популярную статью о кодировках с балансом между точностью, объемом и незанудностью. Насколько это [не] удалось — судить Вам, уважаемые читатели.

                        Не могу согласиться с формулировкой: «Кодовая страница — это таблица соответствия набора символов, их кодов и способа хранения этих кодов. А кодировка — это, строго говоря, способ хранения этих кодов сам по себе». Мне ближе формулировка из Википедии: "Кодовая страница (англ. code page) — таблица, сопоставляющая каждому значению байта некоторый символ (или его отсутствие)". В этом случае термины «Кодировка» и «кодовая страница» по сути синонимы (не абсолютные, но очень близкие). Мне кажется, важнее понимать, что это такое и с чем это едят, чем спорить о том, какая формулировка правильная.

                        Насчет некорректности «детского» вопроса «Почему не использовали Unicode» я соглашусь. Но вопрос «почему в персональных ОС не использовали 16-битную кодировку, ведь их предполагалось продавать по всему миру?» меня интересовал. Свою точку зрения я написал, но если кто знает «почему» из более авторитетных источников, напишите, пожалуйста — я буду только рад.
                          +1
                          Мне ближе формулировка из Википедии: «Кодовая страница (англ. code page) — таблица, сопоставляющая каждому значению байта некоторый символ (или его отсутствие)».
                          Википедия — не шибко авторитетный источник. Тут сразу, например, возникает вопрос — причём тут байт? Особенно в свете упомянутых кои-7, utf-8 итд. В той же английской википедии уже несколько по-другому: «a code page is a table of values that describes the character set used for encoding a particular set of glyphs», что более правильно, и ближе всё же к первой процитированной формулировке.

                          Кодовая страница — это, опять же, виртуальная таблица номер-символ. А кодировка уже переводит эти номера в байты(числа). Например, обычно 8-битные кодировки являются простым сопоставлением этого номера символа в число 0..255. Но это не обязательно, примеры есть и в самой статье.
                            0
                            Не хочу погружаться дебри и спорить о тонкостях и точности перевода. Читатель, если захочет, может без труда найти тот вариант, который ему больше нравится.
                            +1
                            По поводу кодировки и кодовой страницы вам уже написали, что англоязычная Википедия отражает суть лучше, потому что это не синонимы (хотя и употребляются в синонимичном значении многими). Я не зря в своем комментарии привел и соответствующие англоязычные термины: они употребляются обычно в более точном строгом значении, а в русском языке при заимствовании смысл был «размыт». Повторю: encoding, кодировка — это способ хранения номеров символов. Например, можно сказать: «семибитная кодировка» или «двухбайтовая кодировка», «мультибайтовая кодировка» — это все способы хранения номеров символов кодовой страницы. Так что чтобы «понимать, что это такое», нужно понимать сразу точно — это не добавляет сложности, зато добавляет ясность и избавляет от разночтений и недопониманий.

                            Что касается того, почему нельзя было пользоваться сразу шестнадцатибитной кодировкой — я уже также сказал об этом. В те времена, когда все это только возникало, балом правили не производители софта, а производители железа. Вот была микросхема контроллера дисплея, например — Motorola MC6845 или Rockwell 6545, и для них таблица символов знакогенератора была зашита в ПЗУ, его изменить без смены ПЗУ было просто нельзя. Вокруг этого и плясали производители софта. Вот например, г-н Фролов, автор популярной в девяностые учебной литературы по персональным компьютерам, пишет:
                            У видеоадаптера CGA таблицы знакогенератора, определяющие символы, которые можно отобразить на экране дисплея в текстовых режимах, находятся в ПЗУ, расположенном вне адресного пространства процессора. Программы не имеют возможности изменить или даже считать информацию из этих таблиц. Поэтому для русификации текстовых режимов видеоадаптера CGA необходимо перепрограммировать ПЗУ знакогенератора. Единственной возможностью отобразить на CGA русские буквы, не перепрограммируя ПЗУ, является использование графических режимов работы адаптера. В графических режимах вы можете сами определить образы символов с ASCII кодами от 128 до 255. Образы символов с ASCII кодами от 0 до 127 нельзя изменить, не перепрограммируя ПЗУ.

                            И это написано, между прочим, через десять лет после появления CGA, когда над стандартом Unicode работа уже шла.
                            А вот когда появился EGA (1984-1985), таблица знакогенератора стала доступна софту, и вот тогда уже можно было говорить о смене кодовой страницы.
                            Соображения для этого были практические: людям реально весьма редко было нужно одновременно показывать на экране, скажем, текст на русском и греческом. А иметь базовый латинский набор символов и собственный алфавит (Кириллицу, например) тогдашние фокусы с переключением кодовых страниц вполне позволяли. По той же приблизительно причине в разном прикладном софте, например — в MySQL, полная поддержка Unicode появилась весьма недавно.
                            –1
                            Давайте еще раз расставим точки над i.
                            1. По поводу кодировки и кодовой страницы вам уже написали, что англоязычная Википедия отражает суть лучше, потому что это не синонимы (хотя и употребляются в синонимичном значении многими).
                            Я не спорил ни с этим высказыванием ни с английской википедией, речь шла о вашей русскоязычной формулировке. Если Вам понятнее — мне не нравится ваш перевод (или толкование): «Кодовая страница — это таблица соответствия набора символов, их кодов и способа хранения этих кодов. А кодировка — это, строго говоря, способ хранения этих кодов сам по себе»
                            2. Не надо превращать популярную (не требующую от читателя глубоких специлизированных знаний) статью в занудство.
                            3. Я отмечал, что понятия кодовой страницы и кодировки близки, но не абсолютные синонимы, но выяснять различия выходит за рамки статьи. Прочитайте первое предложение статьи и название раздела.
                            4. Сами это понятия менялись с течением времени и понятие кодовой страницы в момент ее первого появления отличается от сегодняшнего. Тогда не было мультибайтовых кодировок (еще раз — статья опубликована в разделе история ИТ).

                            Вы делаете упор на железо — Ваше право. Я делаю упор на экономику. Почему железо было сделано таким? Потому, что память была очень дорогая и для англоязычных потребителей смысла удорожать железо не было (дешевле было использовать фокусы). Если у вас есть ссылки на более авторитетные источники — поделитесь ими, иначе спорить бесполезно.

                            Что касается переключения кодовых страниц, то на практике переключать их туда-сюда в процессе работы особой нужды не было: просто при запуске ДОС вместо зашитой в адаптер загружалась альтернативная (чаще всего) и все — дальше работа шла только с ней. С СGA я не работал, а вот с VGA работал довольно активно на уровне железа.
                              0
                              Я отмечал, что понятия кодовой страницы и кодировки близки, но не абсолютные синонимы, но выяснять различия выходит за рамки статьи.
                              Тут просто небольшая путаница произошла. code page вообще несколько специфический (даже «проприетарный», скажем так) термин и стоит в стороне от character set и encoding, про которые в основном должна идти речь. И которые, разумеется, вообще нисколько не близки в статье любого уровня «популярности» про кодировки. НО при этому всё же code page ближе по контексту к термину character set. Хотя обычно он означает и способ кодирования (раньше одно другому соответствовало, т.к. вариантов особо не было). Видимо, про это имел в виду Moskus в своей формулировке о code page (которая мне тоже кажется несколько запутанной).
                              0
                              Прарп

                              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                              Самое читаемое