EssayAI
Блог
Блог
Математика и алгоритмы

Кодировка Windows-1251: как хранится кириллица

11 июня 2026Время чтения: 8 минут
#кодировка Windows-1251#кириллица#таблица символов#байт#кракозябры

Кодировка Windows-1251 - это однобайтовая восьмибитная таблица символов, разработанная Microsoft в начале 1990-х годов специально для представления кириллических букв в операционных системах Windows. На протяжении двух десятилетий она была стандартом де-факто для русскоязычных сайтов, офисных документов и системных сообщений. Несмотря на то что сегодня её постепенно вытесняет Unicode в кодировке UTF-8, Windows-1251 по-прежнему встречается в устаревших базах данных, файловых архивах и конфигурационных файлах - и знать её устройство необходимо любому, кто работает с текстом на уровне байтов. Чтобы сразу увидеть, как каждый символ превращается в последовательность битов, воспользуйтесь калькулятором ниже: он показывает побитовую карту и распределение байт по зонам таблицы.

Структура таблицы Windows-1251

Вся таблица Windows-1251 вмещает ровно 256 символов - по одному на каждое из 256 значений восьмибитного байта (28=2562^8 = 256). Первые 128 позиций (0x00–0x7F, десятичные 0–127) полностью совпадают с таблицей ASCII: цифры 0–9 занимают коды 48–57, заглавные латинские буквы - 65–90, строчные - 97–122. Это означает, что любой ASCII-текст (английский, цифры, знаки препинания) при хранении в Windows-1251 занимает ровно столько же байт и выглядит идентично.

Вторые 128 позиций (0x80–0xFF, десятичные 128–255) - расширенная зона, именно здесь расположена кириллица. Ключевой диапазон:

СимволHexДесятичный
А (заглавная)0xC0192
Б0xC1193
Я0xDF223
а (строчная)0xE0224
б0xE1225
я0xFF255
Ё0xA8168
ё0xB8184

Заглавные буквы А–Я идут подряд в диапазоне 0xC0–0xDF (192–223), строчные а–я - в 0xE0–0xFF (224–255). Буква «ё»/«Ё» стоит отдельно: 0xA8 и 0xB8 - это историческое решение, вызывавшее немало проблем при сортировке. Для перехода от кода строчной буквы к коду заглавной достаточно вычесть 32: код(а)32=22432=192=код(А)\text{код}(\text{а}) - 32 = 224 - 32 = 192 = \text{код}(\text{А}). Такая же разница существует между латинскими строчными и заглавными в ASCII.

Анимация заполнения таблицы Windows-1251: ASCII-зона 0x00–0x7F серая, зона кириллицы 0xC0–0xFF постепенно окрашивается синим. Видно, что каждый символ занимает ровно одну ячейку таблицы - один байт

Как символ превращается в байт

Когда программа сохраняет кириллический текст в Windows-1251, каждый символ заменяется одним числом из таблицы. Слово «Мир» записывается тремя байтами:

М=0xCC=20410,и=0xE8=23210,р=0xF0=24010.\text{М} = 0\text{xCC} = 204_{10}, \quad \text{и} = 0\text{xE8} = 232_{10}, \quad \text{р} = 0\text{xF0} = 240_{10}.

В двоичном виде буква «М» (0xCC) выглядит так: 1100110021100\,1100_2. Старший бит равен 1 - это признак расширенной зоны (коды 128–255). У всех кириллических символов, начиная с 0xC0, старший бит всегда единица, что и отличает их от ASCII-символов, у которых старший бит равен нулю.

Побайтовая раскладка слова «Привет» в Windows-1251: шесть байт, все в диапазоне C0–FF, каждый - ровно 8 бит
Побайтовая раскладка слова «Привет» в Windows-1251: шесть байт, все в диапазоне C0–FF, каждый - ровно 8 бит

Именно восьмой бит (значение 128) «включает» расширенную зону. Это объясняет, почему семибитный ASCII вмещает только 128 символов и для кириллицы не хватает места: нужен восьмой бит, а он уже занят.

Кракозябры: откуда берётся кодировочная путаница

«Кракозябры» - неформальный термин для нечитаемого текста, возникающего при несоответствии кодировок: файл был создан в одной, а открыт в другой. Рассмотрим типичный сценарий.

Буква «П» в Windows-1251 имеет код 0xCF (207). Если тот же байт 0xCF открыть, предполагая кодировку UTF-8, интерпретатор обнаружит, что байт с битом 11 в начале означает начало двухбайтовой последовательности, а следующий байт не является продолжением (не начинается с 10). Это ошибка декодирования, и браузер или текстовый редактор вместо «П» покажет знак замены - обычно символ \lozenge или вопросительный знак в квадрате.

При открытии файла Windows-1251 в кодировке ISO-8859-1 (Latin-1) байт 0xCF попадает в область символа Ï (буква с умляутом) - именно такие латинские символы видят пользователи вместо русского текста.

Главное правило: кодировка - это соглашение, а не свойство самого байта. Байт 0xCF означает «П» только при условии, что обе стороны (запись и чтение) используют Windows-1251. Без этого контракта последовательность байт бессмысленна.

Наиболее распространённые причины кракозябр:

  • Файл .html без тега <meta charset="windows-1251"> или с неверным значением charset.
  • База данных MySQL с полем latin1, в которое записан Windows-1251 текст.
  • Текстовый файл, сохранённый в Notepad в «ANSI» (Windows-1251 для русской Windows), открытый в Linux-редакторе с дефолтной кодировкой UTF-8.
  • Письмо электронной почты с заголовком Content-Type: text/plain; charset=utf-8, тело которого фактически закодировано в Windows-1251.

Windows-1251 против UTF-8: сколько байт на символ

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

UTF-8 использует переменное число байт: от одного (ASCII) до четырёх. Кириллические буквы в Unicode занимают диапазон U+0410–U+044F, и UTF-8 кодирует их двумя байтами:

А=U+0410UTF-8110100000xD0100100000x90\text{А} = \text{U+0410} \xrightarrow{\text{UTF-8}} \underbrace{11010000}_{\text{0xD0}}\,\underbrace{10010000}_{\text{0x90}}

Это значит, что слово «Россия» (6 букв) занимает 6 байт в Windows-1251 и 12 байт в UTF-8. Для коротких текстов разница незначительна, но при хранении миллионов строк в базе данных она становится заметной. С другой стороны, UTF-8 охватывает весь Unicode (более 140 000 символов), тогда как Windows-1251 ограничена 256 позициями - в неё не входят украинские Ї/і/ї, белорусское Ў, ни один иероглиф.

Перекодирование: как починить кракозябры

Когда текстовый файл отображается неверно, исправить ситуацию позволяет перекодирование - замена одной интерпретации байт другой. Инструменты командной строки для этого:

iconv -f windows-1251 -t utf-8 input.txt -o output.txt

В Python 3 перекодирование делается через bytes.decode:

data = open('file.txt', 'rb').read()
text = data.decode('windows-1251')
open('file_utf8.txt', 'w', encoding='utf-8').write(text)

Ключевой момент: нужно точно знать исходную кодировку. Если она неизвестна, помогает эвристический детектор - библиотека chardet в Python или утилита file -i в Linux. Однако короткие тексты (менее 100 байт) определяются ненадёжно: слишком мало статистики для различения Windows-1251 и KOI8-R (другой исторической кириллической кодировки).

В базах данных MySQL перекодирование сложнее: данные хранятся в столбцах с типом latin1 (так называли Windows-1251 в старых версиях MySQL), но приложение читает их как utf8. Исправление требует экспорта в SQL, замены SET NAMES latin1 на SET NAMES cp1251, а затем повторного импорта с параметром --default-character-set=cp1251. После этого все строки нужно сконвертировать командой CONVERT TO CHARACTER SET utf8mb4, которая физически переписывает байты в каждом столбце.

Не путайте «открыть в другой кодировке» и «конвертировать». Первое - лишь меняет интерпретацию тех же байт в редакторе (временно). Второе - физически переписывает байты на диске. При конвертировании важно сначала создать резервную копию.

Частые ошибки

  • Считать, что Windows-1251 и cp1251 - разные кодировки. Это одно и то же: «cp» расшифровывается как code page (кодовая страница), cp1251 - синоним Windows-1251 в Python, Java, Linux.
  • Забывать указывать кодировку в HTTP-заголовке. Браузер определяет кодировку из Content-Type: text/html; charset=windows-1251; без этого он угадывает и часто ошибается.
  • Использовать len() в Python 2 для подсчёта символов в строке Windows-1251. В Python 2 len(s) возвращает длину в байтах, а не символах; корректно декодировать сначала: len(s.decode('cp1251')).
  • Смешивать в одном файле Windows-1251 и UTF-8. Конкатенация двух строк в разных кодировках даёт нечитаемый бинарный мусор.
  • Предполагать, что «кириллица» = Windows-1251. Существуют ещё KOI8-R, KOI8-U, ISO-8859-5, IBM866 - у каждой свои коды для одних и тех же букв.

FAQ

Почему кириллические символы в Windows-1251 начинаются с 0xC0?

Это результат исторического решения Microsoft. Коды 0x80–0xBF были частично заняты псевдографикой и специальными символами (знаки валют, кавычки), а диапазон 0xC0–0xFF оказался свободен от конфликтов с Latin-1. Русские буквы разместили именно туда - подряд, чтобы упростить алфавитную сортировку. «Ё»/«ё» поместили отдельно (0xA8 и 0xB8), потому что таблица уже была заполнена до их стандартизации.

Можно ли хранить в Windows-1251 текст на двух языках, например русском и украинском?

Частично. Windows-1251 содержит большинство украинских букв (Г, Д, З, Л, Н и другие совпадают с русскими), но специфически украинские символы Ї (U+0457) и і (U+0456) отсутствуют в таблице. Для смешанных кириллических текстов с украинским, белорусским или болгарским необходима UTF-8 или специализированные кодировки (KOI8-U для украинского).

Как веб-браузер определяет кодировку страницы?

Браузер проверяет три источника по порядку убывания приоритета: HTTP-заголовок Content-Type (самый надёжный), тег <meta charset="..."> в начале HTML-документа, и наконец - эвристику (статистический анализ байтов). При наличии противоречий побеждает HTTP-заголовок. Именно поэтому тег <meta> помогает при чтении файлов с диска, но может быть проигнорирован сервером.

Коротко

Windows-1251 - однобайтовая кодировка, в которой каждый символ (включая кириллический) занимает ровно 1 байт. ASCII-зона (0x00–0x7F) совпадает с семибитным ASCII; кириллица А–Я и а–я занимают диапазоны 0xC0–0xDF и 0xE0–0xFF, Ё/ё стоят особняком (0xA8/0xB8). Главная проблема кодировки - несовместимость с Unicode: 256 позиций хватает только для одного языкового набора, отсюда кракозябры при смешении кодировок. Для новых проектов используется UTF-8, однако понимание Windows-1251 обязательно при работе с унаследованными системами и отладке текстовых данных.

Доверьте текст нейросети EssayAI

Открыть EssayAI

Бесплатно, на русском языке и без VPN

Читайте также