Как преобразовать массив байт UTF-8 в строку в C#?
Правильное преобразование UTF-8 byte[] в string
Ваша проблема в том, что вы используете Encoding.Default, который применяет системную кодировку (обычно Windows-1251 на русской версии Windows), а не UTF-8. Для корректного декодирования нужно использовать Encoding.UTF8. Вот правильное решение:
byte[] utf8Bytes = new byte[] { 208, 161, 208, 176, 208, 189, 208, 186, 209, 130 };
string result = Encoding.UTF8.GetString(utf8Bytes);
Console.WriteLine(result); // Выводит: Санкт
Теперь разберёмся подробнее. В .NET есть несколько способов работы с кодировками:
Основные методы класса Encoding
- Encoding.UTF8.GetString(byte[]) — декодирует массив байт в строку, предполагая, что байты закодированы в UTF-8.
- Encoding.UTF8.GetBytes(string) — обратная операция: преобразует строку в массив байт UTF-8.
- Encoding.Default — системная кодировка (опасно использовать, так как результат зависит от настроек ОС).
Дополнительные нюансы
Если вы работаете с частичными данными (например, читаете поток по частям), важно учитывать, что UTF-8 использует переменную длину символов (от 1 до 4 байт). В таких случаях используйте Decoder для корректной обработки границ:
byte[] buffer = new byte[1024];
int bytesRead = await networkStream.ReadAsync(buffer, 0, buffer.Length);
Decoder decoder = Encoding.UTF8.GetDecoder();
char[] chars = new char[decoder.GetCharCount(buffer, 0, bytesRead)];
int charsDecoded = decoder.GetChars(buffer, 0, bytesRead, chars, 0);
string result = new string(chars, 0, charsDecoded);
Проверка на null и пустые массивы
Всегда проверяйте входные данные:
public static string ConvertUtf8BytesToString(byte[] bytes)
{
if (bytes == null)
throw new ArgumentNullException(nameof(bytes));
if (bytes.Length == 0)
return string.Empty;
return Encoding.UTF8.GetString(bytes);
}
Работа с BOM (Byte Order Mark)
Иногда UTF-8 данные содержат BOM (первые три байта: 0xEF, 0xBB, 0xBF). Encoding.UTF8.GetString() корректно обрабатывает BOM, но если вы хотите его удалить, используйте new UTF8Encoding(false):
Encoding utf8WithoutBom = new UTF8Encoding(false);
string result = utf8WithoutBom.GetString(bytes);
Производительность
Для больших массивов (мегабайты+) используйте Encoding.UTF8.GetString(byte[], int, int), чтобы избежать копирования подмассива:
string result = Encoding.UTF8.GetString(byteArray, startIndex, length);
Теперь ваш код будет работать корректно с любым UTF-8 текстом, включая русский, китайский или эмодзи.
<<Альтернативный подход через MemoryStream и StreamReader
Если вы работаете с потоками данных (например, из файла или сети), более удобно использовать StreamReader с указанием кодировки UTF-8:
byte[] utf8Bytes = new byte[] { 208, 161, 208, 176, 208, 189, 208, 186, 209, 130 };
using (MemoryStream ms = new MemoryStream(utf8Bytes))
using (StreamReader reader = new StreamReader(ms, Encoding.UTF8))
{
string result = reader.ReadToEnd();
Console.WriteLine(result); // Санкт
}
Когда это полезно
- При чтении данных из файла:
using (StreamReader reader = new StreamReader("file.txt", Encoding.UTF8)). - При работе с сетевыми потоками, где данные приходят частями.
- Если нужно обработать большие объёмы данных без загрузки всего массива в память.
Важное замечание
Не забывайте закрывать StreamReader (или использовать using), чтобы освободить ресурсы. Этот способ чуть медленнее прямого вызова Encoding.UTF8.GetString(), но даёт больше гибкости при работе с потоками.
Ответов пока нет.
Войдите чтобы оставить ответ