Как преобразовать массив байтов (byte[]) в строку (string) в C#?
Основное решение: используйте правильную кодировку
Класс Encoding в C# предоставляет статические методы для преобразования между массивами байтов и строками. Самая распространённая ошибка новичков — использование Encoding.Default, который зависит от региональных настроек системы и может давать непредсказуемый результат на разных компьютерах. Всегда явно указывайте кодировку.
1. Для UTF-8 (рекомендуется для большинства современных данных)
byte[] buffer = { 72, 101, 108, 108, 111 }; // "Hello"
string text = Encoding.UTF8.GetString(buffer);
Console.WriteLine(text); // Выведет: Hello
2. Для ASCII (если данные гарантированно только английские символы)
byte[] asciiBytes = { 65, 66, 67 }; // "ABC"
string asciiText = Encoding.ASCII.GetString(asciiBytes);
3. Для Windows-1251 (русский текст в старых файлах)
byte[] russianBytes = { 209, 128, 209, 131, 209, 129, 209, 129, 208, 186, 208, 184, 208, 185 }; // "русский"
string russianText = Encoding.GetEncoding(1251).GetString(russianBytes);
Как определить кодировку?
Если вы не знаете кодировку заранее, можно попробовать два подхода:
- BOM (Byte Order Mark): Проверьте первые байты массива. Для UTF-8 это 0xEF, 0xBB, 0xBF. Для UTF-16 LE — 0xFF, 0xFE.
- Автоопределение: Используйте библиотеку
Ude.NetStandard(порт Mozilla Charset Detector). Пример:
// Установите через NuGet: Install-Package Ude.NetStandard
byte[] data = File.ReadAllBytes("unknown.txt");
using (var detector = new Ude.CharsetDetector())
{
detector.Feed(data, 0, data.Length);
detector.DataEnd();
string encodingName = detector.Charset; // например, "UTF-8"
string text = Encoding.GetEncoding(encodingName).GetString(data);
}
Обратный процесс: строка → массив байтов
Для записи строки обратно в массив байтов используйте метод GetBytes():
string myString = "Привет, мир!";
byte[] bytes = Encoding.UTF8.GetBytes(myString);
Важные замечания
- Не используйте
Encoding.Default— это системная кодировка, которая может быть разной на разных компьютерах. - Если ваш массив байтов содержит нулевые символы (0x00), строка может быть обрезана. Используйте
ReadString()изBinaryReaderдля строк с префиксом длины. - Для работы с бинарными данными, которые не являются текстом (например, изображения), не пытайтесь преобразовать их в строку — используйте
Convert.ToBase64String()для безопасного представления.
Альтернативный подход: использование MemoryStream и StreamReader
Если вы работаете с потоком данных и хотите прочитать строку с возможностью выбора кодировки, можно использовать комбинацию MemoryStream и StreamReader. Это удобно, когда массив байтов содержит несколько строк или смешанные данные.
byte[] buffer = { 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100 }; // "Hello World"
using (var memoryStream = new MemoryStream(buffer))
using (var reader = new StreamReader(memoryStream, Encoding.UTF8))
{
string text = reader.ReadToEnd();
Console.WriteLine(text); // Выведет: Hello World
}
Когда это полезно?
- Если массив байтов содержит несколько строк, разделённых символами новой строки (\n).
- Если нужно читать данные порциями (например, через
ReadLine()). - Если кодировка может быть определена на основе BOM (StreamReader автоматически распознаёт BOM для UTF-8 и UTF-16).
Недостатки
Этот способ немного медленнее прямого вызова Encoding.GetString() из-за создания дополнительных объектов. Для простых преобразований лучше использовать первый вариант.