История кодировок: ASCII, ISO-8859, Windows-1251, UTF-8
Эволюция кодировок от ASCII до Unicode, проблемы кириллицы, почему UTF-8 победил.
Введение
Если вы начинали работать с компьютерами в 1990-х, вы наверняка помните «кракозябры» — бессмысленный набор символов, который появлялся вместо русских букв в письмах, на веб-страницах и в текстовых файлах. Это было следствием того, что в мире существовало несколько несовместимых кодировок, и программа, ожидавшая одну, получала данные в другой. История того, как человечество решало эту проблему — от телеграфа и IBM/360 до Unicode и UTF-8 — это история стандартизации, компромиссов и, в конечном счёте, победы здравого смысла. В этой статье пройдём по основным вехам эволюции кодировок.
Для практической работы с Unicode используйте наш Unicode конвертер.
До Unicode: кодировки для каждой задачи
В ранние годы компьютерной эры не было единого стандарта на кодирование символов. Каждый производитель оборудования придумывал свою таблицу. IBM использовала EBCDIC, мини-компьютеры DEC — свой набор, персоналки Apple — свой. Это создавало хаос при обмене данными.
Первой попыткой стандартизации стал ASCII, опубликованный в 1963 году. Он задал фундамент, на котором строились все последующие кодировки. Но даже ASCII не решил всех проблем: он был рассчитан только на английский язык.
ASCII: стандарт, изменивший всё
ASCII (American Standard Code for Information Interchange) был разработан в 1963 году Американским национальным институтом стандартов (ANSI). Стандарт присваивал 128 символов числам от 0 до 127:
- 0–31 — управляющие символы (перевод строки, табуляция, конец передачи и т. д.);
- 32 — пробел;
- 33–47 — знаки препинания и спецсимволы;
- 48–57 — цифры 0–9;
- 58–64 — дополнительные знаки препинания;
- 65–90 — заглавные латинские буквы A–Z;
- 91–96 — дополнительные символы;
- 97–122 — строчные латинские буквы a–z;
- 123–126 — дополнительные символы;
- 127 — DEL (удаление).
Важное свойство ASCII: он использовал только 7 бит из 8. Восьмой бит был зарезервирован для контроля чётности при передаче по ненадёжным линиям. Впоследствии именно этот «свободный» бит стал основой для создания национальных кодировок.
ASCII стал фундаментом, на котором держится весь современный интернет. И сегодня, в эпоху Unicode, любой ASCII-текст является валидным UTF-8 текстом — это не случайность, а результат продуманного дизайна UTF-8.
Восьмибитные кодировки: эпоха фрагментации
С распространением ПК стало понятно, что ASCII не хватает для других языков. Решение казалось очевидным: использовать восьмой бит и расширить таблицу до 256 символов. Так появились десятки «расширенных» кодировок — по одной или несколько на каждый язык.
Проблема в том, что 256 символов хватало либо на один алфавит, либо на несколько родственных, но не на все сразу. Русский, греческий, иврит, арабский, тайский — каждому нужен был свой набор в диапазоне 128–255. И эти наборы конфликтовали друг с другом: код 0xC0 в одной кодировке означал русскую «А», в другой — греческую «Α», в третьей — символ псевдографики.
ISO 8859: попытка стандартизации
В 1987 году ISO опубликовало семейство стандартов ISO 8859 — 16 различных кодировок, каждая для своего региона:
| Стандарт | Регион / язык |
|---|---|
| ISO 8859-1 (Latin-1) | Западная Европа: английский, французский, немецкий, испанский, итальянский и др. |
| ISO 8859-2 (Latin-2) | Центральная Европа: чешский, польский, венгерский |
| ISO 8859-3 (Latin-3) | Южная Европа: турецкий, мальтийский, эсперанто |
| ISO 8859-4 (Latin-4) | Северная Европа: эстонский, латышский, литовский |
| ISO 8859-5 | Кириллица |
| ISO 8859-6 | Арабский |
| ISO 8859-7 | Греческий |
| ISO 8859-8 | Иврит |
| ISO 8859-9 (Latin-5) | Турецкий |
| ISO 8859-15 (Latin-9) | Пересмотр Latin-1 с добавлением символа евро |
Идея была благая, но реализация оказалась проблемной. Каждая программа должна была знать, в какой кодировке получены данные, и переключаться между ними. Если пользователь открывал файл с текстом на чешском, ожидая западноевропейскую кодировку, — получал «кракозябры».
Windows-1251: фактический стандарт рунета
На практике ISO 8859-5 для кириллицы почти не прижился. В России и СНГ доминирующей стала кодировка Windows-1251, разработанная Microsoft для русскоязычной Windows. Коды в ней расположены так, чтобы кириллица шла подряд и была удобна для обработки.
| Диапазон | Содержание |
|---|---|
| 0x00–0x7F | ASCII (как в базовой таблице) |
| 0x80–0x9F | Спецсимволы, типографские знаки, псевдографика |
| 0xA0–0xFF | Кириллица: А–Яа–пр–яЁё и дополнительные символы |
В Windows-1251 русская «А» имеет код 0xC0 (192), а «я» — 0xFF (255). Кириллица расположена компактно, что упрощает программирование. В 1990-е и начале 2000-х Windows-1251 была стандартом де-факто для русскоязычного веба.
KOI8-R: наследие Unix
Параллельно в Unix-сообществе и в почтовых системах использовалась кодировка KOI8-R (Код Обмена Информацией, 8-битный). У неё было интересное свойство: если «сбросить» старший бит (то есть интерпретировать как ASCII), русские буквы превращались в фонетически похожие латинские. Например, «Привет» становилось «pR IWET». Это позволяло прочитать текст даже при неправильной передаче через 7-битный канал.
CP866: наследие MS-DOS
В эпоху MS-DOS для кириллицы использовалась кодировка CP866 (или «альтернативная кодировка ГОСТ»). В ней русские буквы расположены иначе, чем в Windows-1251, и есть обширный блок псевдографики для рисования рамок в текстовом режиме. Сегодня CP866 можно встретить в консольных приложениях Windows и в некоторых legacy-системах.
Проблема нескольких кодировок
В 1990-х годах русскоязычный пользователь сталкивался с тем, что один и тот же текст приходилось хранить в разных кодировках:
- Windows-1251 — для офисных документов и веб-страниц;
- KOI8-R — для электронной почты и Unix-систем;
- CP866 — для DOS-приложений и консоли;
- ISO 8859-5 — в редких «стандартных» системах.
Если пользователь получал письмо в KOI8-R, а его почтовый клиент был настроен на Windows-1251, текст превращался в нечитаемый набор символов. То же самое происходило на веб-страницах: браузер пытался угадать кодировку по содержимому, но часто ошибался.
Unicode: амбициозный проект
В конце 1980-х годов две группы инженеров параллельно пришли к идее единой кодировки для всех языков мира. В 1987 году Джо Бекер из Xerox и Ли Коллинз из Apple начали проект Unicode. В 1991 году был создан Unicode Consortium, и в том же году вышла первая версия стандарта.
Идея Unicode: каждому символу каждой письменности присвоить уникальный номер (code point). Первоначально планировалось ограничиться 16 битами (65 536 символов), но быстро стало ясно, что этого мало — одних только китайских иероглифов больше 70 000. Сегодня Unicode поддерживает 1 114 112 code points, из которых около 150 000 уже заняты.
UTF-8: гениальное решение
С расширением Unicode возникла проблема: как хранить code points в памяти? Простейший подход — UTF-32, по 4 байта на символ — расточителен для европейских языков. UTF-16 экономнее, но несовместим с ASCII: любой ASCII-текст нужно было перекодировать.
В 1992 году Кен Томпсон и Роб Пайк, работавшие над операционной системой Plan 9, предложили UTF-8 — кодировку переменной длины, обратно совместимую с ASCII. Каждый символ занимает от 1 до 4 байтов:
- 1 байт — символы ASCII (0–127);
- 2 байта — латиница с диакритикой, кириллица, греческий, арабский, иврит;
- 3 байта — китайский, японский, корейский, остальные BMP-символы;
- 4 байта — эмодзи, исторические письменности, редкие символы.
Гениальность UTF-8 в том, что любой ASCII-текст автоматически является валидным UTF-8. Это значит, что все старые программы продолжали работать без изменений. Подробнее о UTF-8 читайте в нашей статье о Unicode и UTF-8.
Принятие UTF-8: медленная, но верная победа
Несмотря на очевидные преимущества, UTF-8 внедрялся медленно. В 1990-х и начале 2000-х многие разработчики не видели смысла переходить: «У нас всё работает в Windows-1251, зачем нам UTF-8?». Но по мере глобализации интернета и роста количества пользователей в Азии и других неевропейских регионах необходимость универсальной кодировки стала очевидной.
Перелом наступил в середине 2000-х, когда крупные веб-сервисы (Google, Wikipedia, Amazon) перешли на UTF-8. HTML5 (2014 год) объявил UTF-8 кодировкой по умолчанию. Сегодня, согласно статистике W3Techs, UTF-8 использует более 98% всех веб-страниц в мире.
В России переход с Windows-1251 на UTF-8 занял примерно с 2005 по 2012 год. Сегодня Windows-1251 встречается только в legacy-системах и в очень старых архивах.
Современные кодировки и форматы
UTF-8
Доминирующая кодировка в вебе, JSON, XML, конфигурационных файлах. Используется в Linux, macOS, большинстве современных фреймворков и библиотек.
UTF-16
Используется внутри Windows API, JavaScript (движки V8 и SpiderMonkey хранят строки как UTF-16), Java, .NET. Программист обычно не замечает этого, но это создаёт нюансы при работе с эмодзи и суррогатными парами.
UTF-32
Используется очень редко, в основном в специализированных приложениях для обработки текста, где важна простота индексирования. Например, в некоторых библиотеках регулярных выражений.
Сравнение кодировок: размер текста
Размер одного и того же текста в разных кодировках существенно различается. Возьмём фразу «Привет, мир!» (12 символов):
| Кодировка | Размер | На символ |
|---|---|---|
| Windows-1251 | 12 байт | 1 байт |
| KOI8-R | 12 байт | 1 байт |
| UTF-8 | 22 байта | ~1.83 байта (10 кириллицы × 2 + 2 ASCII × 1) |
| UTF-16 (без BOM) | 24 байта | 2 байта |
| UTF-16 (с BOM) | 26 байт | 2 байта + 2 байта BOM |
| UTF-32 (без BOM) | 48 байт | 4 байта |
Для русского текста UTF-8 в два раза больше Windows-1251, но для английского — столько же. Это компромисс, на который пришлось пойти ради универсальности: один и тот же файл может содержать любой язык мира без переключения кодировок.
Эпохальные вехи
| Год | Событие |
|---|---|
| 1838 | Сэмюэл Морзе демонстрирует электрический телеграф |
| 1874 | Эмиль Бодо создаёт 5-битную кодировку для телеграфа |
| 1928 | IBM внедряет перфокарты с 80 колонками |
| 1963 | Опубликован ASCII |
| 1964 | IBM/360 использует EBCDIC |
| 1981 | IBM PC с кодовой страницей 437 |
| 1987 | ISO публикует семейство ISO 8859 |
| 1990 | Microsoft выпускает Windows-1251 для кириллицы |
| 1991 | Создан Unicode Consortium, первая версия Unicode |
| 1992 | Кен Томпсон и Роб Пайк разрабатывают UTF-8 |
| 1996 | JavaScript использует UTF-16 внутри |
| 2000 | UTF-8 объявлен RFC 3629 |
| 2007 | Google переключает индекс на UTF-8 |
| 2014 | HTML5 объявляет UTF-8 кодировкой по умолчанию |
| 2015 | Эмодзи стандартизированы в Unicode 8.0 |
Уроки истории
История кодировок учит нескольким важным вещам:
1. Обратная совместимость — ключ к успеху
UTF-8 победил во многом потому, что был обратно совместим с ASCII. Старые программы продолжали работать, и переход мог быть постепенным. Если бы Unicode потребовал мгновенного перехода, он бы не состоялся.
2. Несколько стандартов хуже, чем один посредственный
Сосуществование Windows-1251, KOI8-R и CP866 создавало бесконечные проблемы. Любой компромиссный единый стандарт лучше, чем несколько «идеальных».
3. Универсальность побеждает эффективность
UTF-8 в два раза больше Windows-1251 для русского текста. Но эта цена была заплачена без колебаний ради того, чтобы один и тот же файл мог содержать любой язык мира.
4. Каналы связи диктуют форматы
Появление каждого нового стандарта было ответом на ограничения существующих каналов связи: телеграф → 5 бит, мейнфреймы → EBCDIC, интернет → ASCII → Unicode.
Заключение
История кодировок — это история компромиссов между эффективностью, совместимостью и универсальностью. От 5-битной кодировки Бодо через ASCII и десятки национальных стандартов мир пришёл к Unicode и UTF-8 — единой кодировке, которая поддерживает все языки, все письменности и даже эмодзи. Сегодня проблема «кракозябр» почти исчезла, но понимание истории помогает ценить то, что у нас есть, и не повторять старых ошибок при разработке новых стандартов.
Для работы с Unicode и конвертации между кодировками используйте наш Unicode конвертер. А если хотите глубже понять UTF-8 — читайте нашу статью о Unicode и UTF-8, а для общего обзора методов кодирования — сравнительный обзор.
Попробуйте эти инструменты
Похожие статьи
Base64 — что это и как работает
Принцип кодирования Base64, алфавит, padding, использование в Data URI, email, API. Примеры кодирования.
URL кодирование: percent-encoding explained
Что такое URL encoding, зарезервированные символы, как кодировать/декодировать URL, частые ошибки.
HTML сущности и кодирование спецсимволов
HTML entities, named vs numeric, XSS защита, кодирование кавычек, амперсандов, угловых скобок.
JWT токен: структура и как декодировать
JSON Web Token: header, payload, signature. Как работает аутентификация JWT, безопасность, декодирование.