Как преобразовать массив байтов UTF-8 (byte[]) в строку (string) в C#?
Использование класса Encoding.UTF8
Для преобразования массива байтов в строку с учётом кодировки UTF-8 в C# используется статический класс System.Text.Encoding. Основной метод — GetString(), который принимает массив байтов и опционально начальный индекс и длину.
Вот правильное решение вашей задачи:
using System;
using System.Text;
public class Program
{
public static void Main()
{
byte[] data = new byte[] { 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100 };
// Преобразование всего массива
string result = Encoding.UTF8.GetString(data);
Console.WriteLine(result); // Выведет: Hello World
// Работа с частью массива (индекс 0, длина 5)
string part = Encoding.UTF8.GetString(data, 0, 5);
Console.WriteLine(part); // Выведет: Hello
}
}
Важные нюансы и альтернативы
- Кириллица и Unicode: UTF-8 корректно обрабатывает любые символы, включая кириллицу, иероглифы и эмодзи. Пример:
byte[] cyrillic = Encoding.UTF8.GetBytes("Привет, мир!"); string text = Encoding.UTF8.GetString(cyrillic); Console.WriteLine(text); // Привет, мир! - Обработка неполных данных: Если вы получаете данные частями (например, из сети), используйте
Decoderдля буферизации:Decoder decoder = Encoding.UTF8.GetDecoder(); byte[] partialData = new byte[] { 208, 159, 209 }; // Начало слова "Привет" char[] chars = new char[decoder.GetCharCount(partialData, 0, partialData.Length, false)]; int charsDecoded = decoder.GetChars(partialData, 0, partialData.Length, chars, 0, false); string partialString = new string(chars, 0, charsDecoded); Console.WriteLine(partialString); // Может вывести "П" или "Пр" в зависимости от границы - Производительность: Для больших массивов (сотни мегабайт) используйте перегрузку
GetString(ReadOnlySpan<byte>)в .NET Core 3.0+:ReadOnlySpan<byte> span = data.AsSpan(); string fastResult = Encoding.UTF8.GetString(span); - Ошибки декодирования: По умолчанию
Encoding.UTF8выбрасываетDecoderFallbackExceptionпри невалидных байтах. Чтобы избежать этого, задайте fallback:Encoding safeEncoding = Encoding.GetEncoding("UTF-8", EncoderFallback.ReplacementFallback, DecoderFallback.ReplacementFallback); string safeResult = safeEncoding.GetString(data);
Почему не работает data.ToString()?
Метод ToString() для массивов в C# не переопределён для вывода содержимого — он возвращает имя типа (System.Byte[]). Для преобразования байтов в строку всегда используйте Encoding.
Заключение
Основной способ — Encoding.UTF8.GetString(byteArray). Он прост, надёжен и поддерживает все символы Unicode. Для потоковой обработки используйте Decoder, а для повышения производительности — Span<T>. Всегда помните про возможные ошибки декодирования и задавайте fallback при работе с ненадёжными данными.
Использование System.Text.Encoding.UTF8.GetString() с учётом длины
Когда вы работаете с буферами, которые могут быть больше, чем фактические данные (например, при чтении из сокета), обязательно указывайте реальную длину данных, а не длину массива:
byte[] buffer = new byte[1024];
int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
string message = Encoding.UTF8.GetString(buffer, 0, bytesRead); // Только прочитанные байты
Если вы передадите весь массив (buffer.Length), то в строку попадут нулевые байты (\0), что может привести к неожиданным результатам или ошибкам.
Дополнительный совет: использование MemoryStream и StreamReader
Если вы предпочитаете более высокоуровневый подход, можно использовать StreamReader:
using (var ms = new MemoryStream(byteArray))
using (var reader = new StreamReader(ms, Encoding.UTF8))
{
string result = reader.ReadToEnd();
}
Этот способ удобен, когда байты уже представлены в виде потока, но для простого массива Encoding.UTF8.GetString() быстрее и лаконичнее.