Все статьи
Кодирование

Двоичное кодирование текста: как работает

Текст в binary, ASCII таблица, как компьютеры хранят текст, конвертация между системами счисления.

19 февраля 2025
7 мин чтения
ConvertHub
#binary#ascii#кодирование

Введение

Компьютер не понимает букв, слов или предложений — он понимает только нули и единицы. Всякий раз, когда вы набираете на клавиатуре латинскую «A» или русскую «П», компьютер преобразует этот символ в последовательность битов, и именно эти биты хранятся в памяти, передаются по сети и сохраняются на диске. Как именно происходит это преобразование? Чем кодирование латиницы отличается от кириллицы? Почему эмодзи весят больше, чем буквы? В этой статье разберём двоичное кодирование текста от первой принципы: от бита и байта до Unicode.

Сразу попрактиковаться можно в наших инструментах: текст в двоичный и двоичный в текст.

Биты, байты и системы счисления

Минимальная единица информации — бит. Он может принимать два значения: 0 или 1. Восемь битов образуют байт, который может принимать 256 различных значений (от 00000000 до 11111111, или от 0 до 255 в десятичной системе).

Помимо двоичной (base-2), байты часто записывают в более компактных системах:

  • Десятичная (base-10) — привычные цифры от 0 до 255. Например, латинская «A» имеет код 65.
  • Шестнадцатеричная (base-16, hex) — цифры 0–9 и буквы A–F. Код «A» — 0x41. Один байт записывается двумя hex-цифрами. Подробнее — в нашей статье о hex кодировании.
  • Восьмеричная (base-8) — цифры 0–7. Сегодня почти не используется.
  • Двоичная (base-2) — восемь цифр 0/1 на байт. Самый «низкий» уровень представления.

Для числа 65 (буква «A»):

Десятичная:     65
Шестнадцатеричная: 0x41
Восьмеричная:   0101
Двоичная:       01000001

ASCII: первая таблица кодирования

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

Несколько важных кодов ASCII:

СимволДесятичныйHexДвоичный
пробел320x2000100000
!330x2100100001
0480x3000110000
9570x3900111001
A650x4101000001
Z900x5A01011010
a970x6101100001
z1220x7A01111010
~1260x7E01111110
DEL1270x7F01111111

Восьмой бит в байте ASCII изначально оставался свободным и использовался для контроля чётности при передаче. Позже его стали задействовать в расширенных кодировках — прежде всего для кириллицы, греческого, арабского и других алфавитов.

Кодирование кириллицы

ASCII не содержит русских букв, поэтому для кириллицы было создано несколько взаимоисключающих кодировок: KOI8-R, CP866, Windows-1251, ISO 8859-5. Все они используют восьмой бит и кодируют русские буквы кодами от 128 до 255, но по-разному.

КодировкаГде использоваласьОсобенность
KOI8-RUnix, email, FidoNetПри «сбросе» 8-го бита кириллица превращается в латиницу (читаемая транслитерация)
CP866MS-DOSИспользовалась в консольных программах DOS
Windows-1251Windows, вебСтала фактическим стандартом в русскоязычном вебе в 1990-х
ISO 8859-5РедкоОфициальный стандарт ISO, мало где применялся

В Windows-1251 русская «А» имеет код 0xC0 (192), а русская «я» — 0xFF (255). Буквы идут подряд, что упрощает программирование. Но из-за существования нескольких кодировок пользователи часто видели «кракозябры» — текст, открытый в неправильной кодировке. Окончательно проблема решилась с приходом Unicode и UTF-8. Подробнее — в статье об истории кодировок.

Unicode и UTF-8: современный подход

Unicode присваивает каждому символу уникальный номер (code point). UTF-8 кодирует эти номера переменным числом байтов: 1 для ASCII, 2 для кириллицы и большинства европейских письменностей, 3 для китайского и японского, 4 для эмодзи и исторических письменностей.

Сравним двоичное представление строки «Привет» в разных кодировках:

КодировкаРазмерДвоичное представление (hex)
Windows-12516 байтCF F0 E8 E2 E5 F2
UTF-812 байтD0 9F D1 80 D0 B8 D0 B2 D0 B5 D1 82
UTF-1612 байт (+2 BOM)FF FE 1F 04 40 04 38 04 32 04 35 04 42 04
UTF-3224 байт1F 04 00 00 40 04 00 00 ...

В UTF-8 кириллица занимает 2 байта на символ, что в 2 раза больше, чем в Windows-1251. Это плата за универсальность: один и тот же файл может содержать русский, китайский и эмодзи одновременно, без переключения кодировок. Подробнее о UTF-8 — в статье о Unicode и UTF-8.

Как преобразовать текст в двоичный

Алгоритм прост: для каждого символа определить его числовой код в нужной кодировке, представить это число в двоичной системе и при необходимости дополнить нулями слева до нужной длины (7 бит для ASCII, 8 для байта, 16 для UTF-16 code unit и т. д.).

Пример: кодируем «Hi» в ASCII

H = 72 = 01001000
i = 105 = 01101001

Итог: 01001000 01101001

Пример: кодируем «Привет» в UTF-8

П = U+041F → UTF-8: D0 9F → 11010000 10011111
р = U+0440 → UTF-8: D1 80 → 11010001 10000000
и = U+0438 → UTF-8: D0 B8 → 11010000 10111000
в = U+0432 → UTF-8: D0 B2 → 11010000 10110010
е = U+0435 → UTF-8: D0 B5 → 11010000 10110101
т = U+0442 → UTF-8: D1 82 → 11010001 10000010

Итог (по байтам):
11010000 10011111 11010001 10000000 11010000 10111000
11010000 10110010 11010000 10110101 11010001 10000010

JavaScript: текст в двоичный и обратно

// Текст в двоичный (по байтам UTF-8)
function textToBinary(text) {
  const bytes = new TextEncoder().encode(text);
  return Array.from(bytes)
    .map(b => b.toString(2).padStart(8, '0'))
    .join(' ');
}

textToBinary('Hi');
// "01001000 01101001"

textToBinary('Привет');
// "11010000 10011111 11010001 10000000 ..."

// Двоичный в текст
function binaryToText(bin) {
  const bytes = bin.split(' ').map(s => parseInt(s, 2));
  return new TextDecoder('utf-8').decode(new Uint8Array(bytes));
}

binaryToText('01001000 01101001');
// "Hi"

Обратите внимание на использование TextEncoder и TextDecoder. Они работают с UTF-8 по умолчанию и корректно обрабатывают многобайтовые символы. Не пытайтесь делать преобразование через charCodeAt — для эмодзи и суррогатных пар результат будет неверным.

Python: текст в двоичный

def text_to_binary(text):
    return ' '.join(format(b, '08b') for b in text.encode('utf-8'))

def binary_to_text(binary):
    bytes_list = bytes(int(b, 2) for b in binary.split())
    return bytes_list.decode('utf-8')

print(text_to_binary('Hi'))
# '01001000 01101001'

print(text_to_binary('Привет'))
# '11010000 10011111 11010001 10000000 ...'

print(binary_to_text('01001000 01101001'))
# 'Hi'

Применения двоичного представления текста

1. Отладка и анализ данных

Если в файле есть непечатные символы или вы подозреваете, что кодировка определена неверно, дамп в двоичном или hex виде поможет разобраться. Hex dump — стандартный инструмент при работе с бинарными форматами.

2. Обучение и понимание

Преобразование текста в двоичный — классическая задача в курсах информатики. Она помогает студентам понять, как компьютер хранит данные, и подготовиться к более сложным темам: сжатию, шифрованию, обработке изображений.

3. Шифрование и обфускация

Иногда двоичное представление используют как простейший способ «спрятать» текст — например, в тривиальных CTF-задачах. Это не настоящая защита, потому что любой может раскодировать строку обратно. Для реальной защиты используйте криптографию.

4. Кодирование в Base64 и Hex

Base64 и hex — это тоже способы представления байтов в виде текста. Но они начинаются с двоичного представления. Подробнее о Base64 читайте в нашей статье о Base64 кодировании, о hex — в материале о hex кодировании.

Биты и символы: длина строки

Длина строки в символах не равна длине в байтах и не равна длине в битах. Например, строка «Привет, мир!»:

  • 12 символов
  • 12 байт в Windows-1251
  • 22 байта в UTF-8 (10 кириллицы × 2 + 2 ASCII)
  • 24 байта в UTF-16 + 2 байта BOM = 26 байт
  • 48 байт в UTF-32 + 4 байта BOM = 52 байта
  • 176 бит в UTF-8 (22 × 8)

Поэтому при работе с текстом важно понимать, в какой кодировке он хранится. Если функция ожидает длину в байтах, а ей передают длину в символах — результат будет некорректным.

Распространённые ошибки

1. Игнорирование кодировки

Многие начинающие разработчики предполагают, что «символ = байт». Для ASCII это так, но для любого другого языка — нет. Если ваш код режет строку посимвольно через индексы байтов, для русского текста он разрежет буквы пополам.

2. Смешивание кодировок

Если вы прочитали файл в Windows-1251 и пытаетесь вывести его в HTML с UTF-8, увидите «кракозябры». Всегда явно указывайте кодировку при чтении и записи.

3. Использование charCodeAt для эмодзи

// НЕПРАВИЛЬНО: вернёт код первого суррогата
'😀'.charCodeAt(0);  // 55357

// ПРАВИЛЬНО: вернёт полный code point
'😀'.codePointAt(0);  // 128512

// Безопасная длина
[...'😀'].length;  // 1, а не 2

4. Забытый BOM

Если вы сохранили файл в UTF-8 с BOM, а потом склеиваете его с другим содержимым, BOM может оказаться в середине документа и сломать парсинг. В PHP это классическая проблема:session_start() не работает, потому что перед <?php есть невидимые три байта BOM.

Зачем вообще «двоичный текст»

В чистом виде двоичное представление текста (строки нулей и единиц) почти не используется на практике — слишком громоздко. Но как промежуточное звено в обучении и в алгоритмах оно незаменимо. Понимание того, как «A» превращается в 01000001, — основа для понимания всех остальных схем кодирования: Base64, hex, Data URI, шифрования.

Кроме того, двоичное представление полезно для понимания работы побитовых операций: AND, OR, XOR, сдвигов. Эти операции часто применяются в криптографии, обработке изображений и низкоуровневом программировании.

Заключение

Двоичное кодирование текста — это фундамент, на котором построены все более высокие уровни абстракции. Зная, как символ превращается в биты, вы сможете разобраться в любой кодировке, понять, почему возникают «кракозябры», и правильно работать с текстом в любом языке программирования.

Для практической конвертации используйте наши инструменты: текст в двоичный и двоичный в текст. А если хотите глубже погрузиться в тему — читайте наши статьи о Unicode и UTF-8 и об истории кодировок.

Попробуйте эти инструменты

Похожие статьи