Символы — это не байты
Компьютер хранит байты, значения от 0 до 255. Люди читают символы: буквы, цифры, знаки препинания, эмодзи. Кодировка символов — это согласованное отображение между ними. Ошибитесь в отображении, и вы увидите классический искажённый текст (café, превращающийся в café), что почти всегда является несоответствием между кодировкой, использованной для записи байтов, и той, что использована для их чтения.
ASCII: исходные 128
Старейшая широко используемая кодировка — ASCII, которая присваивает числа от 0 до 127 базовым английским буквам, цифрам и распространённым символам. Семь бит, 128 символов. ASCII прост и до сих пор лежит в основе большой части вычислений, но 128 символов не могут представить буквы с диакритикой, нелатинские письменности или символы, поэтому его никогда не хватало для текста мира.
Unicode: одно число на символ
Unicode решает проблему охвата, давая каждому символу уникальное число, называемое кодовой точкой, записываемое как U+0041 (буква A) или U+2615 (горячий напиток). Unicode — это гигантский каталог символов и их кодовых точек, далеко за сто тысяч, охватывающий по существу всякую используемую письменность.
Принципиально: Unicode говорит, какое число у каждого символа, но не как хранить это число как байты. Эта вторая задача принадлежит форме кодирования.
UTF-8: как кодовые точки становятся байтами
UTF-8 — доминирующий способ превращения кодовых точек Unicode в байты, и это значение по умолчанию во всей современной сети. Он переменной длины: символ занимает от одного до четырёх байтов в зависимости от своей кодовой точки.
- Диапазон ASCII (U+0000 до U+007F) кодируется как один байт, идентичный ASCII. Поэтому UTF-8 обратно совместим: любой чисто ASCII-текст уже является корректным UTF-8.
- Символы за пределами ASCII используют два, три или четыре байта. Так,
é— это два байта, а☕— три, хотя каждый является одним символом.
Последний пункт — обычная неожиданность: один символ не всегда один байт. Подсчёт байтов и подсчёт символов дают разные ответы для любого не-ASCII-текста. (UTF-16 и UTF-32 — альтернативные кодировки тех же кодовых точек; UTF-8 выиграл сеть благодаря совместимости с ASCII и компактности для латинского текста.)
Где вступает Base64
Это важно для Base64, потому что Base64 работает с байтами, а не с символами. Чтобы закодировать строку в Base64, строку нужно сначала превратить в байты с помощью кодировки символов, и эта кодировка по существу всегда UTF-8. Закодируйте тот же символ другой схемой, и вы получите другие байты, а значит, другой Base64. Поэтому полный конвейер для текста таков: символы становятся байтами (UTF-8), затем байты становятся безопасным текстом (Base64). При декодировании вы обращаете оба шага.
Инструмент Base64 кодирует текст как байты UTF-8 перед кодированием в Base64 и помечает, когда декодированный результат не является корректным UTF-8, всё в вашем браузере.