Как закодировать текст UTF-8 в Base64
- Введите или вставьте текст в поле Ввод · текст. В поле Кодировка уже выбран UTF-8.
- Base64 появляется в поле Результат · Base64. Счётчик Ввод под инструментом показывает число байтов в UTF-8, а счётчик над полем считает символы так, как это делает JavaScript, поэтому эмодзи идёт за 2.
- Для URL и токенов отметьте URL-safe (- _) и Без дополнения (=), а для почты или PEM выберите Перенос строк.
- Скопируйте результат или скачайте его как
base64.txt.
Base64 в UTF-8 превращает результат обратно в текст.
Как UTF-8 превращает символы в байты
UTF-8 тратит от 1 до 4 байтов на кодовую точку. ASCII остаётся в 1 байте, поэтому английский текст кодируется одинаково в UTF-8 и ASCII. Всё остальное занимает больше:
| Символ | Кодовая точка | Байты UTF-8 | Base64 |
|---|---|---|---|
A | U+0041 | 41 | QQ== |
é | U+00E9 | C3 A9 | w6k= |
€ | U+20AC | E2 82 AC | 4oKs |
日本語 | U+65E5 U+672C U+8A9E | 9 байтов, по 3 на символ | 5pel5pys6Kqe |
😀 | U+1F600 | F0 9F 98 80 | 8J+YgA== |
Base64 добавляет к байтам ещё треть, так что предложение на китайском или японском при переходе от символов к символам Base64 вырастает примерно вчетверо, а один эмодзи превращается в 8 символов. Помните об этом, если у поля есть ограничение длины; поможет калькулятор размера.
Последовательности эмодзи и оттенки кожи
То, что выглядит как один эмодзи, часто состоит из нескольких склеенных кодовых точек. Оттенок кожи задаётся отдельным модификатором, а эмодзи семей и профессий соединяют нескольких человек невидимым соединителем нулевой ширины (U+200D):
| Эмодзи | Кодовых точек | Байтов UTF-8 | Base64 |
|---|---|---|---|
| 😀 | 1 | 4 | 8J+YgA== |
| 👍🏽 | 2 (большой палец + средний оттенок кожи) | 8 | 8J+RjfCfj70= |
| 👨👩👧 | 5 (три человека + два соединителя) | 18 | 8J+RqOKAjfCfkanigI3wn5Gn |
Если разрезать строку Base64 или её декодированные байты посреди такой последовательности, останутся битые символы, так что никогда не обрезайте закодированный UTF-8 на произвольном байте.
Один текст, разные байты: нормализация Unicode
У некоторых символов в Unicode два корректных написания. é может быть одной кодовой точкой U+00E9 (составная форма, NFC) или e, за которой идёт U+0301 COMBINING ACUTE ACCENT (разложенная форма, NFD). Выглядят они одинаково, но байты разные:
| Текст | Форма | Байты | Base64 |
|---|---|---|---|
é | NFC | C3 A9 | w6k= |
é | NFD | 65 CC 81 | ZcyB |
naïve | NFC | 6 | bmHDr3Zl |
naïve | NFD | 7 | bmFpzIh2ZQ== |
Имена файлов в старой файловой системе Apple HFS+ хранятся в разложенной форме, а большинство клавиатур выдают составной текст. Если вы сравниваете значения Base64, подписываете их или используете как ключи, сначала нормализуйте. Этот инструмент кодирует ровно те кодовые точки, которые вы вставили, и ничего не нормализует.
UTF-8 в Base64 в коде
В JavaScript TextEncoder всегда выдаёт UTF-8. Если ввод может приходить из разных источников, сначала нормализуйте:
const text = "e\u0301".normalize("NFC");
Buffer.from(text, "utf8").toString("base64"); // "w6k=" (Node.js)
new TextEncoder().encode(text); // Uint8Array [195, 169]
В браузерах байты из TextEncoder можно передать в bytes.toBase64(), где он поддерживается (Uint8Array.toBase64), или через вспомогательную функцию на btoa со страницы о JavaScript.
import base64, unicodedata
s = unicodedata.normalize("NFC", "nai\u0308ve")
base64.b64encode(s.encode("utf-8")).decode() # 'bmHDr3Zl'
Про файлы и потоковую обработку читайте в статье Base64 в Python.
Вопросы и ответы
Чем Base64 от UTF-8 отличается от обычного Base64?
Ничем. Base64 всегда кодирует байты, а «UTF-8 в Base64» лишь уточняет, какие именно. Для простого ASCII-текста байты UTF-8 совпадают с байтами ASCII, так что результат одинаковый в обоих случаях.
Почему две одинаковые на вид строки дают разный Base64?
В Unicode некоторые символы можно записать несколькими способами. é как одна кодовая точка кодируется в w6k=, а e плюс комбинируемое ударение – в ZcyB. Если значения должны совпадать, приведите текст к NFC перед кодированием.
Добавляет ли кодировщик метку порядка байтов UTF-8 (BOM)?
Нет. Результат начинается сразу с байтов вашего текста. Если получатель требует BOM, Base64 должен начинаться с 77u/ (так кодируются байты EF BB BF).
Сколько байтов занимает эмодзи?
Одна кодовая точка эмодзи занимает в UTF-8 4 байта. Эмодзи с оттенком кожи или семьи состоят из нескольких кодовых точек: 👍🏽 занимает 8 байтов, а семья 👨👩👧 – 18.