Base64 в C#: как кодировать и декодировать строки без головной боли
Вы когда-нибудь сталкивались с ситуацией, когда нужно передать бинарные данные через текстовый протокол, отправить изображение в JSON или сохранить хеш в читаемом виде? Именно здесь на сцену выходит Base64 — старый, добрый, надёжный формат, который превращает любые байты в безопасный текст.
Вопрос "How do I encode and decode a base64 string?" — один из самых популярных на Stack Overflow (десятки тысяч просмотров). И не зря: в C# работа с Base64 кажется простой, но подводные камни встречаются на каждом шагу. Сегодня мы разберём всё от А до Я: от базовых примеров до реальных кейсов из продакшена.
Что такое Base64 и зачем он нужен?
Base64 — это способ представления бинарных данных (байтов) в виде ASCII-строки. Алфавит состоит из 64 символов: A-Z, a-z, 0-9, плюс символы '+' и '/'. На конце строки часто добавляется символ '=' для выравнивания.
Где применяется:
- Передача данных в JSON/XML — бинарные данные нельзя вставлять напрямую, только в виде строки
- Аутентификация — Basic Auth использует Base64 для кодирования логина и пароля
- Хранение изображений в БД — маленькие картинки хранят прямо в базе как Base64
- Email вложения — MIME-формат требует Base64 для бинарных файлов
В C# за всё это отвечает класс System.Convert — ваш главный инструмент для работы с Base64.
Как закодировать строку в Base64 на C#
Самый частый сценарий: у вас есть обычная строка (например, "Привет, мир!"), и вы хотите получить её Base64-представление.
Вот как это делается:
using System;
using System.Text;
string original = "Hello, World!";
byte[] bytes = Encoding.UTF8.GetBytes(original);
string base64 = Convert.ToBase64String(bytes);
Console.WriteLine(base64); // Вывод: SGVsbG8sIFdvcmxkIQ==
Важный момент: Base64 работает с байтами, а не со строками. Поэтому сначала мы преобразуем строку в массив байтов (используя кодировку UTF-8), а затем кодируем эти байты.
Почему UTF-8, а не, скажем, ASCII? Потому что UTF-8 поддерживает все символы Unicode, включая кириллицу, иероглифы и эмодзи. Если вы используете ASCII для русских строк, данные потеряются.
Как декодировать Base64 обратно в строку
Обратный процесс — декодирование — выглядит зеркально:
using System;
using System.Text;
string base64 = "SGVsbG8sIFdvcmxkIQ==";
byte[] bytes = Convert.FromBase64String(base64);
string decoded = Encoding.UTF8.GetString(bytes);
Console.WriteLine(decoded); // Вывод: Hello, World!
Обратите внимание: если вы кодировали строку в UTF-8, то и декодировать нужно в UTF-8. Иначе получите кракозябры.
Работа с бинарными данными (изображения, файлы)
Base64 не ограничивается строками. Вы можете кодировать любые бинарные данные — например, изображение или PDF.
Пример: кодируем массив байтов в Base64
byte[] imageBytes = File.ReadAllBytes("photo.jpg");
string base64Image = Convert.ToBase64String(imageBytes);
// Теперь можно сохранить строку в JSON или отправить по API
Console.WriteLine($"Длина Base64 строки: {base64Image.Length} символов");
Декодируем обратно в файл:
string base64Image = "..."; // ваша строка
byte[] imageBytes = Convert.FromBase64String(base64Image);
File.WriteAllBytes("decoded_photo.jpg", imageBytes);
Важно: Base64 увеличивает размер данных примерно на 33%. Если у вас изображение 1 МБ, после кодирования оно будет весить ~1.33 МБ в виде строки.
Типичные ошибки и как их избежать
Даже опытные разработчики иногда спотыкаются на Base64. Вот самые частые грабли:
- Неправильная кодировка — если вы закодировали строку в UTF-8, а декодируете в ASCII, получите битые данные. Всегда используйте одну и ту же кодировку.
- Лишние пробелы или символы перевода строки — Base64 строка не должна содержать пробелов. Если вы получили её из JSON, проверьте, не добавились ли лишние символы.
- Неверная длина строки — если строка повреждена (например, удалили один символ),
Convert.FromBase64Stringвыбросит исключениеFormatException. - Пустая строка — попытка декодировать пустую строку вызовет ошибку. Всегда проверяйте входные данные.
Продвинутые приёмы: работа с потоками (Streams)
Если вы имеете дело с большими файлами (сотни мегабайт), загрузка всего файла в память может быть неэффективной. Используйте CryptoStream для потокового кодирования/декодирования:
using System.Security.Cryptography;
// Потоковое кодирование в Base64
using (FileStream fs = File.OpenRead("large_file.bin"))
using (MemoryStream ms = new MemoryStream())
using (CryptoStream cs = new CryptoStream(ms, new ToBase64Transform(), CryptoStreamMode.Write))
{
fs.CopyTo(cs);
cs.FlushFinalBlock();
string base64 = Encoding.ASCII.GetString(ms.ToArray());
}
// Потоковое декодирование
string base64 = "...";
byte[] bytes = Convert.FromBase64String(base64);
using (MemoryStream ms = new MemoryStream(bytes))
using (FileStream fs = File.Create("output.bin"))
using (CryptoStream cs = new CryptoStream(ms, new FromBase64Transform(), CryptoStreamMode.Read))
{
cs.CopyTo(fs);
}
Этот подход экономит память и ускоряет работу с большими объёмами данных.
Base64 и URL-безопасность
Стандартный Base64 использует символы '+' и '/', которые могут быть проблемой в URL. Для таких случаев существует URL-safe Base64:
string base64 = Convert.ToBase64String(bytes);
string urlSafe = base64
.Replace('+', '-')
.Replace('/', '_')
.TrimEnd('=');
// Обратно
string standard = urlSafe
.Replace('-', '+')
.Replace('_', '/');
// Добавляем символы '=' обратно (длина должна быть кратна 4)
while (standard.Length % 4 != 0) standard += "=";
Такой подход часто используется в JWT-токенах и API-ключах.
Производительность: что нужно знать
Кодирование и декодирование Base64 — достаточно быстрые операции. Но есть нюансы:
- Маленькие строки — накладные расходы на вызов метода могут быть заметны. Для сот