UTF-8 byte[] to string in C#: which method is faster and better?

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Why the "UTF-8 byte[] to string" question remains relevant?



Imagine: you received a byte array from a network request, read a binary file, or deserialized data from an API. Inside is plain text in Russian, English, or emojis. But C# only sees byte[]. Your task is to turn these zeros and ones into a readable string.



It seems simple, right? One method call and you're done. But on Stack Overflow, the question "How to convert UTF-8 byte[] to string" gathers thousands of views and dozens of answers. Why? Because the devil is in the details: encoding, performance, safety, and unexpected exceptions.



In this article, we won't just give you ready-made code. We will compare approaches, measure speed, discuss pitfalls, and choose the best tool for each task. If you write in C# and work with networks, files, or serialization — this material is for you.



The Problem: byte[] is not a string



In C#, the string type is stored in UTF-16 encoding. But the bytes you received are most likely encoded in UTF-8 (the standard for the internet, JSON, most text protocols). Direct type casting is impossible — the compiler will throw an error.



You need a decoder that converts a sequence of UTF-8 bytes into UTF-16 characters. And here's where it gets interesting: a developer has at least three fundamentally different paths.



Method 1: The Classic — Encoding.UTF8.GetString



The most obvious and Microsoft-recommended way is to use the static class System.Text.Encoding:



byte[] utf8Bytes = { 72, 101, 108, 108, 111, 32, 208, 191, 209, 128, 208, 176, 208, 178, 208, 176 }; // "Hello права"string result = Encoding.UTF8.GetString(utf8Bytes);Console.WriteLine(result); // Output: Hello права


Pros:

  • Simplicity — one line of code.
  • Support for all encodings, including UTF-8, UTF-16, ASCII, Latin-1.
  • Built-in BOM (Byte Order Mark) handling — if there is a UTF-8 marker at the beginning of the array, it will be ignored.
  • Safety — no unsafe blocks.


Cons:

  • Each call creates a new string and an internal buffer.
  • If the bytes are corrupted or contain an invalid UTF-8 sequence, the method will throw a DecoderFallbackException by default (if fallback is not configured).
  • Not optimal for very large arrays (hundreds of megabytes) — double data copying.


When to use?

In 95% of cases. This is the industry standard. If you are not writing a high-load parser or working with gigabytes of logs — use Encoding.UTF8.GetString.



Method 2: Fast and Dangerous — unsafe with pointers



For those chasing speed and not afraid of unsafe. The idea: we know that UTF-8 and UTF-16 are different encodings, but if the array contains only ASCII characters (codes up to 127), each byte can be "stretched" into a 2-byte character without decoding.



unsafe string UnsafeAsciiBytesToString(byte[] bytes){    fixed (byte* pBytes = bytes)    {        return new string((sbyte*)pBytes, 0, bytes.Length);    }}


This code works only for ASCII! For Russian text (characters > 127), the result will be garbage. But for pure English, it works 2-3 times faster than Encoding.UTF8.GetString.



Pros:

  • Minimal overhead — no copying, no decoding.
  • Ideal for parsing HTTP headers, JSON keys (if they are ASCII).


Cons:

  • Dangerous for multi-byte characters — data corruption.
  • Requires enabling unsafe in the project (not always allowed).
  • Does not handle

Blogs

Book Recommendations