Перейти к содержимому

Кодовая страница Windows-1251

Кодовая страница — однобайтовая таблица, сопоставляющая 256 числам конкретные символы. Windows-1251 (CP1251) — такая таблица для кириллицы: первые 128 позиций совпадают с ASCII, русские буквы занимают диапазон 0xC0-0xFF.

Как устроена таблица на 256 позиций

Однобайтовая кодировка — это простая договорённость: байт со значением 65 означает «A», байт 192 означает «А». Восемь бит дают 256 вариантов, и половину из них съедает базовый набор: позиции 0-31 отведены управляющим кодам, 32-126 — латинице, цифрам и знакам препинания, ровно как в базовом наборе ASCII. На национальный алфавит остаётся верхняя половина, 128-255, и именно она отличает одну кодовую страницу от другой.

Windows-1251 разложила кириллицу в верхней половине по алфавиту и почти непрерывно: заглавная А имеет код 0xC0 (192), Я — 0xDF (223), строчная а — 0xE0 (224), я — 0xFF (255). Из этого следует удобное свойство: разница между заглавной и строчной буквой всегда равна 32, как и в латинице, поэтому смена регистра в старом коде делалась одной арифметической операцией. Буквы Ё и ё в стройный ряд не попали и вынесены отдельно — 0xA8 и 0xB8, что до сих пор порождает баги в самописных функциях перевода регистра. В той же верхней половине лежат типографские кавычки, длинное тире, знак номера (0xB9) и буквы других славянских языков на кириллице; одна позиция, 0x98, не определена вовсе.

Главное ограничение очевидно: в 256 ячеек не помещается ничего, кроме одного алфавита плюс латиницы. Русский и греческий в одном файле, китайский иероглиф, знак рубля или эмодзи в CP1251 недоступны в принципе. Именно это ограничение и снял Юникод, где номера символов не привязаны к размеру байта.

CP866, KOI8-R и UTF-8: чем отличаются соседи

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

  • CP866 — кодировка DOS, до сих пор используется в консоли Windows (команда chcp 866) и в .bat-файлах. Часть верхней половины занята символами псевдографики для рамок.
  • KOI8-R — стандарт раннего рунета. Буквы разложены не по алфавиту, а так, чтобы при потере старшего бита получалась читаемая латинская транслитерация: текст портился, но смысл сохранялся — ценное свойство для каналов связи 1970-1980-х.
  • ISO 8859-5 — международный вариант кириллицы, у нас почти не прижился.
  • UTF-8 — не кодовая страница, а форма записи Юникода переменной длины: латиница по одному байту, кириллица по два. Сегодня это выбор по умолчанию для веба, баз данных и обмена файлами.

Windows-1251 остаётся живой не из ностальгии, а из-за инфраструктуры: выгрузки из старых конфигураций 1С, CSV-файлы для Excel, обмен с кассовыми программами, драйверы принтеров этикеток, промышленные контроллеры и базы данных с исторической кодировкой таблиц. Пока такая система в контуре, файлы приходится готовить в её кодировке.

Крякозябры: как читать симптом и чинить причину

Мусор вместо текста почти всегда означает, что байты целы, а таблица при чтении выбрана не та. Симптом указывает на диагноз довольно точно.

Последовательности вроде «ÐŸÑ€Ð¸Ð²ÐµÑ‚» означают, что файл сохранён в UTF-8, а открыт как Windows-1251: двухбайтовое представление русской буквы прочиталось как два отдельных знака верхней половины. Обратная ситуация — текст в CP1251, прочитанный как UTF-8, — даёт ромбы с вопросительным знаком или прямое сообщение о некорректной последовательности. Строки вида «п»я─п╦п╡п╣я┌» указывают на пару CP866 и CP1251. А вот сплошные знаки вопроса — плохой признак: это не отображение, а потеря, символ уже был заменён при сохранении и восстановлению не подлежит.

Чинится это тремя способами. Переоткрыть файл в правильной кодировке (в Notepad++ пункт «Кодировки — Преобразовать в UTF-8», в редакторах VS Code — переключатель в статусной строке). Перекодировать пакетно утилитой iconv, указав исходную и целевую страницы. Или устранить причину: явно задавать кодировку при выгрузке, ставить BOM для CSV, который открывают в Excel, и хранить внутренние данные только в UTF-8. Созвучное, но совсем другое понятие разобрано в термине кодек: он сжимает сигнал, а не сопоставляет символам числа.

Кодовые страницы в QR-кодах и штрих-кодах

В QR-коде кодировка объявляется механизмом ECI: значение 000022 соответствует Windows-1251, 000026 — UTF-8. По умолчанию, без указания ECI, стандарт предписывает считать данные записанными в ISO 8859-1, где кириллицы нет вовсе, поэтому строгие промышленные сканеры выдают вместо русского текста латиницу с диакритикой. Телефоны обычно угадывают UTF-8 по структуре байтов, и именно поэтому одна и та же наклейка на смартфоне читается нормально, а на терминале сбора данных — нет. Что и как класть в текстовый код, разобрано в термине QR-код с произвольным текстом.

В линейных штрих-кодах ситуация жёстче. Code 128 кодирует только символы ASCII с номерами 0-127, то есть русских букв в нём быть не может; EAN-13 хранит одни цифры. Поэтому наименование товара кириллицей печатают текстом рядом с кодом, а в сам код кладут артикул или GTIN. Отсюда типичная ошибка при печати этикеток: программа отдаёт название в CP1251, принтер ждёт другую страницу, и на ленте появляется мусор — при том что сам штрих-код сканируется правильно, ведь цифры в обеих таблицах совпадают. Сгенерировать корректный линейный код можно в генераторе штрих-кодов.

Частые вопросы

Windows-1251 и ANSI — это одно и то же?

В русской Windows пункт меню «ANSI» в диалогах сохранения означает именно кодовую страницу системы, то есть CP1251. Название историческое и неточное: настоящего стандарта ANSI за ним не стоит, а на системе с другой локалью тот же пункт даст другую таблицу. Поэтому в требованиях к файлу лучше писать «Windows-1251», а не «ANSI».

Как перевести файл из CP1251 в UTF-8 без потерь?

Потерь не будет: все символы CP1251 есть в Юникоде. Подойдёт Notepad++ с пунктом преобразования кодировки, любой современный редактор кода с переключателем в статусной строке или утилита iconv с явным указанием исходной и целевой кодировки. Главное — не «сохранить как» из программы, которая уже показывает крякозябры: так вы зафиксируете неверное прочтение.

Почему Excel открывает мой CSV с иероглифами?

Excel определяет кодировку по системным настройкам и без явных признаков считает файл однобайтовым. Есть два рабочих решения: сохранить CSV в UTF-8 с BOM — тремя служебными байтами в начале файла, по которым Excel опознаёт кодировку, — либо выгружать файл прямо в Windows-1251, если получатель работает со старой системой и других символов в данных нет.

Можно ли записать русский текст в QR-код в Windows-1251?

Можно, указав ECI 000022, и такой вариант иногда нужен для интеграции со старым оборудованием, которое ждёт однобайтовые данные. Для публичных кодов это плохой выбор: часть сканеров ECI игнорирует и покажет мусор. Универсальное решение — UTF-8, а ещё надёжнее вовсе избежать вопроса, положив в код латинскую ссылку.

Кириллица в коде занимает больше места?

Да. В UTF-8 русская буква занимает два байта против одного у латинской, поэтому текст на кириллице вдвое быстрее исчерпывает ёмкость символа и поднимает его версию — модули становятся мельче, а требования к печати выше. В Windows-1251 буква умещается в один байт, но экономия не окупает риск несовместимости со сканерами.