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

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

Исторический контекст: от кода Морзе до Unicode

Первой «цифровой» письменностью стал телеграфный алфавит Сэмюэля Морзе (1838). Он использовал всего два знака — точку и тире — для кодирования букв и цифр. Это был прообраз двоичного кодирования, лежащего в основе современных компьютеров.

В 1963 году стандарт ASCII (American Standard Code for Information Interchange) унифицировал представление 128 символов 7-битовыми кодами. Но он охватывал только латиницу. Решением стало появление Unicode в 1991 году — универсального стандарта, присваивающего уникальный номер (code point) каждому знаку почти всех письменностей мира.

📊 Какую кодировку вы чаще всего встречаете в работе?
UTF-8
ASCII
Windows-1251
Другую/не знаю

Алфавит, строка и язык: формальные основы

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

Например, алфавит {0, 1} порождает язык всех двоичных строк. А язык программирования Python — это множество строк, корректных с точки зрения его грамматики. Компилятор или интерпретатор проверяет принадлежность введённого текста к языку.

⚠️ Внимание: не путайте алфавит как множество символов с набором глифов шрифта. Один и тот же символ (code point) может отображаться разными глифами в зависимости от шрифта и локали.

Системы счисления как вид письменности

Позиционные системы счисления — это специализированные письменности для представления чисел. Двоичная (база 2) используется процессорами, шестнадцатеричная (база 16) — программистами для компактной записи байтов, восьмеричная (база 8) — в правах доступа Unix.

Запись числа 255 в разных системах: 11111111₂, 377₈, FF₁₆. Это один и тот же объект, но разные строковые представления. Выбор системы зависит от контекста: человек читает hex, машина работает с битами.

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

Выполнено: 0 / 4

Кодировки символов: от байта к кодовой точке

Стандарт Unicode определяет code point (кодовую точку) — число, присвоенное символу. Но для хранения в памяти нужна кодировка — правило превращения кодовых точек в последовательность байтов.

Самая распространённая — UTF-8. Она использует 1–4 байта на символ: латиница занимает 1 байт, кириллица — 2, эмодзи — 4. Это обеспечивает обратную совместимость с ASCII. UTF-16 (2 или 4 байта) применяется внутри Java, JavaScript, Windows API. UTF-32 (всегда 4 байта) удобен для случайного доступа, но расточителен по памяти.

КодировкаРазмер символаASCII-совместимаГде применяется
UTF-81–4 байтаДаВеб, Linux, БД, JSON
UTF-162 или 4 байтаНетJava, JS, Windows, Qt
UTF-324 байтаНетВнутренние буферы, ICU
Windows-12511 байтНетЛегаси Windows (кириллица)
Почему UTF-8 стал стандартом де-факто?

UTF-8 изобрёл Кен Томпсон за ночь в 1992 году. Гениальность в том, что байты 0x00–0x7F кодируются сами собой (как в ASCII), а старшие биты служат маркерами длины последовательности. Это позволяет искать подстроки байтовым сравнением, не декодируя весь текст. Также UTF-8 не имеет проблем с порядком байтов (endianness), в отличие от UTF-16/32.

Разметка и структурированные данные

Языки разметки (Markup Languages) — это письменности для описания структуры документа. HTML задаёт семантику веб-страницы, XML — произвольные древовидные данные, Markdown — упрощённый формат для чтения человеком.

Сериализационные форматы JSON, YAML, TOML — тоже письменности, но ориентированные на структуры данных (объекты, массивы, скаляры). Они имеют строгий синтаксис: пропущенная запятая в JSON делает весь документ невалидным.

Пример JSON-объекта:

{

"encoding": "UTF-8",

"version": 2,

"enabled": true

}

⚠️ Внимание: никогда не парсьте HTML регулярными выражениями. HTML — нерегулярный язык (в смысле теории Хомского), а regex работает только с регулярными. Используйте полноценные парсеры: BeautifulSoup, lxml, DOMParser.
💡

В JSON ключи всегда в двойных кавычках. Одинарные кавычки или их отсутствие — синтаксическая ошибка. Используйте валидаторы (jsonlint.com) перед отправкой в API.

Программные языки: письменность для исполнения

Языки программирования — это формальные письменности с операционной семантикой. Текст программы не просто хранит информацию, он предписывает действия исполнителю (процессору, виртуальной машине, интерпретатору).

Лексический анализатор (лексер) разбивает исходный код на токены — ключевые слова, идентификаторы, литералы, операторы. Синтаксический анализатор (парсер) строит АСТ (абстрактное синтаксическое дерево) по грамматике языка. Дальше — семантический анализ, оптимизация, генерация кода.

Пример токенизации строки x = 42 в Python:

NAME    'x'

EQUAL '='

NUMBER '42'

NEWLINE '\n'

💡

Любая программа — это текст на формальном языке. Качество кода (читаемость, отсутствие багов) напрямую зависит от понимания программистом правил этой письменности: лексики, синтаксиса, семантики.

Проблемы интернационализации (i18n)

Современная письменность в IT должна поддерживать мультиязычность. Это не только Unicode. Нужно учитывать: направление письма (LTR/RTL для арабского, иврита), лигатуры (сочетание глифов), нормализацию (NFC/NFD — разные способы представления одного визуального символа), сортировку (collation) по правилам локали.

Пример: символ é может быть одной кодовой точкой U+00E9 (NFC) или двумя — e + U+0301 (NFD). Визуально одинаковы, но бинарно разные. Поиск и сравнение строк требуют предварительной нормализации.

⚠️ Внимание: функция .toLowerCase() в JavaScript работает некорректно для некоторых локалей (например, турецкого «İ» → «i» с точкой). Всегда используйте .toLocaleLowerCase('tr') с явным указанием локали.
Что такое графема и почему length лжёт?

В Unicode «символ» (code point) ≠ «визуальный символ» (графема). Эмодзи 👨‍👩‍👧‍👦 — это 5 кодовых точек (U+1F468 U+200D U+1F469 U+200D U+1F467 U+200D U+1F466), склеенных Zero Width Joiner. В JS "👨‍👩‍👧‍👦".length === 11. Для работы с графемами нужен Intl.Segmenter или библиотека grapheme-splitter.

Будущее: бинарные форматы и эффективность

Текстовые форматы (JSON, XML, YAML) читаемы людьми, но избыточны и медленны в парсинге. Для высоконагруженных систем используют бинарные письменности: Protocol Buffers (protobuf), MessagePack, CBOR, Avro, FlatBuffers.

Они кодируют схему данных отдельно от полезной нагрузки. Поле «user_id: 12345» в JSON занимает ~15 байт, в protobuf — 2–3 байта (varint). Парсинг в 10–100 раз быстрее. Но читать такой файл в текстовом редакторе нельзя — нужен десериализатор со схемой.

Выбор между текстовым и бинарным форматом — компромисс между наблюдаемостью (debugging, логи) и производительностью (пропускная способность, задержка). Микросервисы часто используют gRPC + protobuf внутри кластера и JSON/REST на границе с внешним миром.

☑️ Выбор формата сериализации

Выполнено: 0 / 4

FAQ: частые вопросы о письменности в IT

Почему в базе данных стоит utf8mb4, а не utf8?

В MySQL старый псевдоним utf8 на самом деле означает utf8mb3 — только 3-байтовые символы (BMP). Эмодзи и редкие иероглифы требуют 4 байта. utf8mb4 — полноценный UTF-8. Всегда используйте utf8mb4 и соответствующие коллации (utf8mb4_unicode_ci).

Чем кодовая страница отличается от кодировки?

Кодовая страница (code page) — термин Microsoft/IBM для однобайтовых кодировок (CP1251, CP866, CP437), где каждому байту 0x00–0xFF ставится в соответствие символ. Кодировка — общее понятие правила отображения кодовых точек в байты, включая многобайтовые (UTF-8, UTF-16).

Зачем нужна BOM (Byte Order Mark)?

BOM (U+FEFF) в начале файла указывает на кодировку и порядок байтов (endianness) для UTF-16/UTF-32. В UTF-8 BOM не нужен (порядок байтов фиксирован), но иногда добавляют для автоопределения. В вебе BOM в UTF-8 вреден — ломает HTTP-заголовки и JSON-парсеры.

Почему регулярные выражения не подходят для парсинга HTML/XML?

HTML/XML — контекстно-свободные языки (Type-2 в иерархии Хомского). Регулярные выражения описывают только регулярные языки (Type-3). Вложенные теги произвольной глубины требуют стека — возможности, которой нет у regex. Используйте DOM-парсеры или SAX/StAX для потокового чтения.

Что такое нормализация Unicode и когда она нужна?

Нормализация приводит эквивалентные последовательности кодовых точек к единому виду. NFC — композиция (один символ, где возможно), NFD — декомпозиция (база + диакритики). Нужна перед сравнением строк, поиском, индексацией в БД, генерацией хэшей. В Python: unicodedata.normalize('NFC', s).