Encoding.UTF8.GetBytes(message) convierte una cadena de C# en un array de bytes, y en casi todos los casos esa es toda la respuesta.
Lo interesante es en qué se diferencian los otros tres enfoques. La conversión explícita (cast) de caracteres a bytes y la llamada a Convert.ToByte() funcionan con un rango reducido de caracteres y se comportan de forma muy distinta cuando una cadena se sale de él, y Encoding.GetEncoding() da acceso a codificaciones con nombre, a un costo que veremos más adelante.
¿Por qué convertir una cadena en un array de bytes en C#?
Una cadena de C# es una secuencia de unidades de código UTF-16, y un array de bytes contiene bytes en bruto sin ningún significado asociado. Una codificación es la regla que convierte una cosa en la otra.
Necesitamos esa regla porque casi nada fuera de nuestro proceso acepta una cadena. Los archivos, los sockets, las funciones hash, las API de cifrado y las colas de mensajes reciben byte[], así que el texto tiene que convertirse en bytes antes de salir de la aplicación.
La respuesta predeterminada en C# es Encoding.UTF8.GetBytes(). Aplica UTF-8 y devuelve un nuevo array de bytes con el tamaño justo.
Lo que importa es qué codificación elegimos. Una cadena como café produce bytes distintos en UTF-8, ASCII, UTF-16 y Latin-1, y quien lea esos bytes más adelante tiene que usar la misma codificación para recuperar el texto original.
Los bytes no guardan ningún registro de la codificación que los produjo. Por eso la codificación es una decisión que tomamos una vez, dejamos por escrito y aplicamos en ambos extremos, y no algo que podamos recuperar más tarde.
El texto no es la única fuente de bytes, claro. El mismo array de bytes puede obtenerse cuando los bytes proceden de un stream, o al leer un archivo directamente en un array de bytes, y todo lo que decimos aquí sobre codificaciones se aplica en el momento en que esos bytes tienen que volver a ser texto.
Sabiendo esto, veamos los distintos métodos para convertir una cadena en un array de bytes.
Antes de empezar
Para todos los ejemplos de código de este artículo, vamos a crear un literal de cadena que convertiremos en un array de bytes:
var message = "Welcome to CodeMaze!";
Con esta cadena, esperamos la misma salida con cada método de conversión:
87,101,108,99,111,109,101,32,116,111,32,67,111,100,101,77,97,122,101,33
¿Cómo convierte Encoding.GetBytes() una cadena?
Encoding.GetBytes() recorre la cadena y escribe la forma codificada de cada carácter en un nuevo array de bytes.
UTF-8 es de ancho variable. Un carácter ASCII ocupa un byte, un carácter latino acentuado como é ocupa dos, la mayoría de los caracteres CJK ocupan tres y 😀 ocupa cuatro. Por eso el array de bytes suele ser más largo que la cadena, y message.Length no es el tamaño del búfer que necesitamos.
Encoding.GetByteCount() nos da ese tamaño. Encoding.GetBytes(ReadOnlySpan<char>, Span<byte>) llena un búfer que ya tenemos, y Encoding.TryGetBytes() hace lo mismo sin lanzar una excepción cuando el búfer resulta ser demasiado pequeño.
Los caracteres que la codificación no puede representar no lanzan una excepción de forma predeterminada. Se reemplazan, y en Encoding.ASCII el reemplazo es un signo de interrogación, así que café da como resultado caf? sin ninguna excepción ni advertencia.
GetBytes() nunca escribe una marca de orden de bytes (BOM). Los tres bytes de la BOM se obtienen con GetPreamble(), y escribirlos es tarea nuestra cuando un consumidor espera recibirla.
Hay varias opciones de codificación y más adelante hablaremos de cómo elegir la adecuada, pero por ahora veamos cómo hacer la conversión con la codificación UTF8:
static byte[] ConvertStringToUTF8Bytes(string message)
{
return Encoding.UTF8.GetBytes(message);
}
Definimos un método estático y devolvemos de inmediato el array de bytes, que ahora contiene la cadena codificada. Para ello usamos el método Encoding.GetBytes(), que aplica la codificación UTF8 a la variable message y convierte los caracteres de la cadena en sus representaciones en bytes correspondientes.

Ebook gratis
¿Tu Web API está lista para producción?
33 puntos que comprobar antes de desplegarla, con la solución de cada uno. Un PDF gratuito de 76 páginas para .NET 10.
El ebook está en inglés.
Descarga la checklist gratisPDF gratuito. Un solo correo para enviártelo. Puedes darte de baja cuando quieras.
¿Qué codificación conviene elegir?
Elegir la codificación “correcta” para convertir cadenas en arrays de bytes depende en gran medida del contexto. Factores como la plataforma de destino, el público, la interoperabilidad y la eficiencia de almacenamiento y transmisión deberían guiar nuestra decisión.
| Codificación | Bytes para "café 😀" (7 caracteres) | Abarca | Úsala cuando |
|---|---|---|---|
Encoding.UTF8 | 10 | Todo Unicode, de 1 a 4 bytes por carácter | La opción predeterminada: web, JSON, archivos, protocolos de red |
Encoding.ASCII | 7, con ? para é y ?? para el emoji | De U+0000 a U+007F | Un consumidor heredado que solo admite ASCII |
Encoding.Latin1 | 7, con é sin cambios y ?? para el emoji | De U+0000 a U+00FF | Un consumidor ISO-8859-1; es la misma codificación que devuelve GetEncoding("ISO-8859-1") |
Encoding.Unicode (UTF-16LE) | 14 | Todo Unicode, 2 o 4 bytes por carácter | Interoperabilidad con una API que espera UTF-16 |
Encoding.UTF32 | 24 | Todo Unicode, 4 bytes por carácter | Indexación de ancho fijo; poco habitual |
Si ninguna de estas opciones encaja porque los bytes tienen que sobrevivir a un cambio de codificación, podemos crear en su lugar una representación en bytes que no dependa de ninguna codificación.
¿Qué ocurre al hacer una conversión explícita de caracteres a bytes?
La conversión explícita de caracteres a bytes ofrece una forma directa de convertir una cadena en un array de bytes, pero es fundamental tener en cuenta sus limitaciones.
La conversión explícita conserva solo el byte menos significativo de cada carácter. Los caracteres de U+0000 a U+00FF sobreviven, así que é (U+00E9) se convierte en 233. Todo lo que está por encima se trunca sin ningún error: Ā (U+0100) se convierte en 0, y un emoji como 😀, que C# almacena como dos caracteres suplentes (surrogates), se convierte en dos bytes que no tienen nada que ver con él. Si convertimos "café 😀" de esta forma, obtenemos 99,97,102,233,32,61,0, que al volver a leerlo da café = seguido de un byte nulo.
Veamos cómo usar esta técnica para la conversión:
static byte[] ConvertStringToByteArrayUsingCasting(string message)
{
var byteArray = new byte[message.Length];
for (int i = 0; i < message.Length; i++)
{
byteArray[i] = (byte)message[i];
}
return byteArray;
}
Inicializamos un array de bytes con un tamaño igual a la longitud de la cadena. Así obtenemos un array de bytes con espacio suficiente para guardar cada carácter de la cadena como un valor de byte. Después iteramos por cada carácter de la cadena, lo que nos permite procesar cada carácter por separado.
Dentro del bucle, asignamos cada carácter a su índice correspondiente en el array de bytes. De este modo, convertimos cada carácter en su valor de byte subyacente y lo almacenamos en el array de bytes.
Por último, devolvemos el array de bytes ya lleno. Este array contiene ahora la representación en bytes de la cadena original, donde el punto de código de cada carácter se almacena como un único byte, algo que solo es posible para los primeros 256 puntos de código.
¿Cuándo lanza Convert.ToByte() una excepción en lugar de convertir?
Este método forma parte de la clase Convert, que ofrece diversas utilidades de conversión entre tipos de datos. Al igual que el método anterior, proporciona una forma directa de convertir un único carácter en su valor de byte. Sin embargo, no está pensado para convertir cadenas enteras en arrays de bytes.
La conversión con esta técnica es sencilla:
static byte[] ConvertStringToByteArrayUsingConvertToByte(string message)
{
var byteArray = new byte[message.Length];
for (int i = 0; i < message.Length; i++)
{
byteArray[i] = Convert.ToByte(message[i]);
}
return byteArray;
}
Aunque este código tiene una estructura parecida a la del ejemplo anterior, usa el método Convert.ToByte() para convertir cada carácter en un byte. Este enfoque ofrece una forma más explícita, y posiblemente más legible, de convertir los caracteres en sus valores de byte correspondientes.
A diferencia de la conversión explícita, Convert.ToByte() se niega a convertir en lugar de truncar: cualquier carácter por encima de U+00FF lanza una OverflowException, lo que lo convierte en el más seguro de los dos bucles, aunque sea el más lento.
¿Qué codificaciones admite Encoding.GetEncoding()?
Este método obtiene un objeto Encoding para una codificación concreta, que después se puede usar en diversas operaciones relacionadas con la codificación, como convertir cadenas en arrays de bytes con GetBytes().
Recurrimos a GetEncoding() cuando algo fuera de nuestro control ya ha elegido una codificación por nosotros: una exportación de ancho fijo de un mainframe, un CSV antiguo, un protocolo anterior a Unicode.
Veamos cómo usar este método:
static byte[] ConvertStringToByteArrayUsingEncoding(string message)
{
var encoding = Encoding.GetEncoding("ISO-8859-1");
var byteCount = encoding.GetByteCount(message);
var byteArray = new byte[byteCount];
encoding.GetBytes(message, byteArray);
return byteArray;
}
Nuestro método usa una codificación para transformar una cadena en su array de bytes correspondiente: obtiene una instancia concreta de la codificación ISO-8859-1 mediante el método Encoding.GetEncoding(). Esta codificación es fundamental para determinar cómo se corresponden los caracteres de la cadena con sus valores de byte.
Después, calcula meticulosamente el número exacto de bytes necesarios para alojar la cadena codificada con encoding.GetByteCount() y crea un array de bytes con ese número de bytes mediante new byte[].
Convierte los caracteres de la cadena en sus valores de byte correspondientes y almacena los bytes codificados en el array proporcionado. Al final, devuelve el array de bytes ya lleno.

Ebook gratis
¿Tu Web API está lista para producción?
33 puntos que comprobar antes de desplegarla, con la solución de cada uno. Un PDF gratuito de 76 páginas para .NET 10.
El ebook está en inglés.
Descarga la checklist gratisPDF gratuito. Un solo correo para enviártelo. Puedes darte de baja cuando quieras.
Encoding.GetEncoding() solo resuelve las codificaciones que .NET registra de forma predeterminada, que forman una lista corta de siete: UTF-8, UTF-16 y UTF-32 en ambos órdenes de bytes, ASCII y Latin-1. ISO-8859-1 está en ella, y por eso el código anterior funciona. Las páginas de códigos de Windows, como 1252, no están en ella: Encoding.GetEncoding(1252) lanza una NotSupportedException que nos indica que registremos un proveedor, y Encoding.GetEncoding("windows-1252") lanza en cambio una ArgumentException, porque no reconoce ese nombre. Basta con llamar una vez a Encoding.RegisterProvider(CodePagesEncodingProvider.Instance) al iniciar la aplicación para recuperarlas todas.
Ese es el comportamiento documentado, no una rareza de nuestro ejemplo. La referencia de Microsoft sobre Encoding.GetEncoding() lo dice directamente: “En .NET Core, el método GetEncoding devuelve las codificaciones que .NET Core admite de forma nativa”.
¿Qué método de conversión es el más rápido?
Ahora que hemos visto varios métodos para convertir una cadena en un array de bytes, vamos a ponerlos a prueba. Analizaremos su rendimiento con benchmarks, primero con una cadena corta y después con una más larga.
Para la cadena corta, usaremos el valor inicial de message, y para la larga le agregaremos algo de texto:
Welcome to CodeMaze, your one-stop destination for mastering all things .NET and C#! Explore a comprehensive learning experience tailored to your programming journey.
Veamos los benchmarks de la cadena corta:
| Method | Mean | Error | StdDev | Gen0 | Allocated | |-------------------------------------- |---------:|---------:|---------:|-------:|----------:| | ConvertShortMessageUsingCasting | 12.84 ns | 0.553 ns | 1.586 ns | 0.0057 | 48 B | | ConvertShortMessageUsingConvertToByte | 13.08 ns | 0.309 ns | 0.330 ns | 0.0057 | 48 B | | ConvertShortMessageToUTF8Bytes | 19.26 ns | 0.539 ns | 1.572 ns | 0.0057 | 48 B | | ConvertShortMessageUsingGetEncoding | 52.66 ns | 0.985 ns | 0.922 ns | 0.0057 | 48 B |
A continuación, tenemos los benchmarks de la cadena larga:
| Method | Mean | Error | StdDev | Median | Gen0 | Allocated | |------------------------------------- |---------:|---------:|---------:|---------:|-------:|----------:| | ConvertLongMessageToUTF8Bytes | 33.68 ns | 0.725 ns | 1.986 ns | 32.96 ns | 0.0229 | 192 B | | ConvertLongMessageUsingGetEncoding | 65.94 ns | 1.345 ns | 2.527 ns | 66.22 ns | 0.0229 | 192 B | | ConvertLongMessageUsingCasting | 78.97 ns | 1.532 ns | 2.385 ns | 78.99 ns | 0.0229 | 192 B | | ConvertLongMessageUsingConvertToByte | 87.19 ns | 0.972 ns | 0.861 ns | 87.55 ns | 0.0229 | 192 B |
Según las mediciones con BenchmarkDotNet 0.15.8 en .NET 10, la conversión explícita de caracteres individuales sigue siendo la forma más rápida de convertir una cadena corta, con Convert.ToByte() tan cerca que ambos se solapan dentro de sus márgenes de error. Con la cadena larga, el orden se invierte: Encoding.GetBytes() es más del doble de rápido que cualquiera de los dos bucles, y Encoding.GetEncoding() le sigue. Todos los métodos asignan los mismos 48 y 192 bytes, así que aquí lo único que los separa es el tiempo.
¿Qué método conviene usar?
Encoding.UTF8.GetBytes() es la respuesta, salvo que algo ajeno a nuestro código ya haya elegido otra codificación. Vale la pena conocer las tres alternativas sobre todo por lo que hacen con los caracteres que no pueden representar, que es donde se diferencian entre sí mucho más que en velocidad.
| Método | Rango que maneja correctamente | Fuera de ese rango | Úsalo cuando |
|---|---|---|---|
Encoding.UTF8.GetBytes(s) | Todo Unicode | Solo un suplente aislado, que se reemplaza por U+FFFD, sin ningún aviso | La opción predeterminada, para todo lo que sale del proceso |
Encoding.ASCII.GetBytes(s) | De U+0000 a U+007F | Se reemplaza por ? (byte 63), sin ningún aviso | El consumidor solo admite ASCII y la pérdida es aceptable |
Encoding.Latin1.GetBytes(s) | De U+0000 a U+00FF | Se reemplaza por el carácter más parecido (best-fit) o por ? (byte 63), sin ningún aviso: U+0100 se convierte en A | Lo exige un consumidor ISO-8859-1 |
Encoding.GetEncoding(name).GetBytes(s) | Lo que abarque la codificación indicada | El mecanismo de reserva (fallback) de la codificación, normalmente ? | Se necesita una codificación heredada concreta y el proveedor está registrado |
Conversión explícita (byte)c en un bucle | De U+0000 a U+00FF | Se trunca al byte menos significativo sin ningún aviso: U+0100 se convierte en 0 | No se recomienda |
Convert.ToByte(c) en un bucle | De U+0000 a U+00FF | Lanza OverflowException | Caracteres individuales, cuando lo que queremos es un fallo explícito |
Literal "text"u8 con .ToArray() | Todo Unicode, en tiempo de compilación | No aplica | La cadena es una constante en tiempo de compilación |
¿Cómo convertir un array de bytes de nuevo en una cadena en C#?
Encoding.GetString() es la otra mitad de la pareja. Recibe un array de bytes y la misma codificación, y puede devolver la cadena original.
La codificación tiene que coincidir. Los bytes escritos como UTF-8 y leídos como ASCII o Latin-1 pueden producir una cadena distinta, y nada en el array de bytes avisa del error, así que la codificación viaja entre los dos extremos como un acuerdo y no como datos.
Los bytes que no son válidos en la codificación elegida se reemplazan en lugar de rechazarse. UTF-8 convierte cada secuencia no válida en el carácter de reemplazo U+FFFD. Para que falle de forma explícita, creamos new UTF8Encoding(false, true), cuyo decodificador lanza una DecoderFallbackException.
El viaje de ida y vuelta solo se puede garantizar con la misma codificación. El texto codificado en UTF-8 y decodificado como UTF-8 vuelve idéntico, salvo que la cadena contenga un suplente aislado. El texto que pasa por ASCII pierde todos los caracteres que ASCII no puede representar, y ningún decodificador puede recuperarlos, porque los bytes que los describían nunca se escribieron.
El método en sí ocupa una sola línea:
static string ConvertUTF8BytesToString(byte[] byteArray)
{
return Encoding.UTF8.GetString(byteArray);
}
La codificación de esta línea tiene que ser la que produjo los bytes, y esa es la única decisión que toma este método.
El texto plano no es el único destino de un array de bytes. Podemos codificar esos bytes en Base64 para transportarlos, convertir el array de bytes en una cadena hexadecimal para mostrarlo o aplicarle un hash, o hacer el camino inverso, partiendo de una cadena hexadecimal. Y si los bytes van a un destino que no es de confianza, cifrar los bytes resultantes es el paso que corresponde entre las dos conversiones.
Conclusión
En este artículo, hemos visto por qué es importante convertir cadenas en arrays de bytes, hemos repasado varios métodos de conversión y hemos destacado la importancia de elegir la codificación y el método de conversión adecuados según el contexto de nuestra aplicación.
Probado con .NET 10.