Формат, на котором сейчас написан почти весь интернет — порядка 98% страниц — набросали ручкой на салфетке в придорожной закусочной. За ужином. И в ту же ночь запустили.
Сентябрь 1992-го, Нью-Джерси. Кен Томпсон и Роб Пайк (те самые, из Bell Labs, делали Unix и Plan 9) сидят в дайнере. Томпсон берёт подложку из-под тарелки и рисует схему кодирования. Это UTF-8. Ночью дописали в коде — и оно поехало. Салфетку, конечно, никто не догадался сохранить — артефакт на миллиард уехал в мусорку с тарелками.
А теперь зачем это понадобилось.
Что было до
Был ASCII. 128 символов — латиница, цифры, знаки препинания и управляющие (перевод строки, табуляция, тот самый нулевой байт). Влезает в 7 бит, всем хорошо. Ровно до тех пор, пока текст на английском.
Кириллица, японский, греческий — для них в ASCII пусто. Стали лепить свои 8-битные кодировки: KOI-8 и Windows-1251 под русский, Latin-1 под Европу, Shift-JIS под японский. Десятки таблиц. И во всех один и тот же байт значит разную букву.
Открываешь письмо — а там «Ïðèâåò». Это не сломанный файл. Это твой «Привет», записанный в Windows-1251 и прочитанный как западный Latin-1: байты те же, таблица другая. Кракозябры — отсюда. Все мы это ловили: то в письме, то в кривой выгрузке из старой базы.
Попробовали починить — придумали Unicode. Первая версия, UCS-2: дай каждому символу ровно 16 бит (два байта), и хватит на всех. Звучит логично. По факту — три проблемы, одна другой больнее. ASCII перестал работать (латинская буква теперь два байта, старый софт давится). Текст распух вдвое. И 65 536 ячеек кончились — одни китайцы с японцами выбрали их под завязку.
Тупик. Зоопарк кодировок есть, замены нет.
Что придумали на салфетке
UTF-8 зашёл иначе. Вопрос не «сколько бит на символ». Вопрос — как ужиться с тем, что уже написано. Отсюда переменная длина: 1–4 байта на символ.
И вот тут кайф:
🔸 Обратная совместимость. Все 128 символов ASCII кодируются одним байтом, как раньше — байт в байт. Любой ASCII-файл за прошлые 30 лет уже валидный UTF-8. Старый софт ничего не заметил.
🔸 Самосинхронизация. По любому байту видно — это начало символа или хвост. Прыгнул в середину потока, поймал ближайшее начало, поехал. Потерялся байт — рассыпался один символ, а не весь текст после него.
🔸 Сортировка по байтам = правильный алфавитный порядок. Без приседаний.
🔸 Нет нулевых байтов внутри символов. В C строка кончается на нулевом байте, и весь сишный мир на этом стоит. UTF-8 нулей внутрь не суёт — строки не рвутся.
Сложи всё вместе — он не ломает старое. Просто ложится сверху. Поэтому и расползся: переходить не больно.
Но не бесплатно
Только не подумай, что халява. За переменную длину тоже платишь. «N-й символ» больше не равен «N-й байт» — прыгнуть к 50-му за раз нельзя, идёшь с начала и считаешь.
Дальше — вес. Латиница 1 байт, кириллица 2, иероглифы 3. За совместимость с ASCII по байтам платят все, кто пишет не латиницей.
И исторический грабли — overlong-кодирование: один символ можно было записать длиннее, чем нужно. Казалось мелочью — пока через это не полезли мимо проверок безопасности: закодируешь / хитро, фильтр не увидел, а система прочитала. Позже залатали, объявив такие формы невалидными.
Ну и 16-битная идея не умерла: её подлатали суррогатными парами и назвали UTF-16 — на нём до сих пор сидят Windows и Java. Но это уже костыль поверх, а не победа.
Зачем это аналитику
Проблему, об которую индустрия билась лет двадцать, два инженера закрыли за ужином. UCS-2 был чище и правильнее — а выиграл формат, который ужился со всем старым барахлом.
И вы ровно это решаете каждый раз, когда садитесь за новую версию API или схему БД: запилить красиво с нуля и сломать совместимость — или натянуть новое поверх старья. UTF-8 намекает, что второе чаще выживает.
А вы какие кодировки в дикой природе ещё застали? Кто чинил «Ïðèâåò» в выгрузке руками — отзовитесь 🙂
@analyst_exe
Post #664
274

- ❤ 4
- 🔥 4