byte[] UTF-8 a string en C#: ¿qué método es más rápido y mejor?

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

¿Por qué la pregunta "UTF-8 byte[] to string" sigue siendo relevante?



Imagina: has recibido un array de bytes de una solicitud de red, has leído un archivo binario o has deserializado datos de una API. Dentro hay texto normal en ruso, inglés o emojis. Pero C# solo ve byte[]. Tu tarea es convertir esos ceros y unos en una cadena string comprensible.



¿Qué podría ser más simple, verdad? Una sola llamada a un método y listo. Pero en Stack Overflow, la pregunta "How to convert UTF-8 byte[] to string" acumula miles de visitas y decenas de respuestas. ¿Por qué? Porque el diablo está en los detalles: codificación, rendimiento, seguridad y excepciones inesperadas.



En este artículo no solo te daremos código listo. Compararemos enfoques, mediremos la velocidad, discutiremos las trampas y elegiremos la mejor herramienta para cada tarea. Si programas en C# y trabajas con redes, archivos o serialización, este material es para ti.



El problema: byte[] no es una cadena



En C#, la cadena string se almacena en codificación UTF-16. Pero los bytes que recibiste probablemente están codificados en UTF-8 (el estándar de internet, JSON, la mayoría de los protocolos de texto). La conversión directa de tipos es imposible: el compilador dará un error.



Se necesita un decodificador que convierta una secuencia de bytes UTF-8 en caracteres UTF-16. Y aquí comienza lo interesante: el desarrollador tiene al menos tres caminos fundamentalmente diferentes.



Método 1: El clásico — Encoding.UTF8.GetString



La forma más obvia y recomendada por Microsoft es usar la clase estática 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); // Salida: Hello права


Ventajas:

  • Simplicidad: una sola línea de código.
  • Soporte para todas las codificaciones, incluyendo UTF-8, UTF-16, ASCII, Latin-1.
  • Manejo integrado de BOM (Byte Order Mark): si hay un marcador UTF-8 al inicio del array, se ignora.
  • Seguridad: sin bloques unsafe.


Desventajas:

  • Cada llamada crea una nueva cadena y un búfer interno.
  • Si los bytes están dañados o contienen una secuencia UTF-8 no válida, el método por defecto lanza una DecoderFallbackException (a menos que se configure un fallback).
  • No es óptimo para arrays muy grandes (cientos de megabytes): doble copia de datos.


¿Cuándo usarlo?

En el 95% de los casos. Es el estándar de la industria. Si no estás escribiendo un analizador de alto rendimiento ni trabajas con gigabytes de registros, usa Encoding.UTF8.GetString.



Método 2: Rápido y peligroso — unsafe con punteros



Para quienes buscan velocidad y no temen al unsafe. La idea: sabemos que UTF-8 y UTF-16 son codificaciones diferentes, pero si el array solo contiene caracteres ASCII (códigos hasta 127), cada byte se puede "expandir" a un carácter de 2 bytes sin decodificación.



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


¡Este código solo funciona para ASCII! Para texto en ruso (caracteres > 127), el resultado será basura. Pero para inglés puro, funciona 2-3 veces más rápido que Encoding.UTF8.GetString.



Ventajas:

  • Gastos generales mínimos: sin copia, sin decodificación.
  • Ideal para analizar encabezados HTTP, claves JSON (si son ASCII).


Desventajas:

  • Peligroso para caracteres multibyte: corrupción de datos.
  • Requiere permiso unsafe en el proyecto (no siempre permitido).
  • No maneja

Blogs

Book Recommendations