Encoding.UTF8.GetBytes(message) converte uma string C# em um array de bytes e, para quase todos os casos, a resposta se resume a isso.
A parte interessante é o que as outras três abordagens fazem de diferente. A conversão explícita de caracteres em bytes e a chamada a Convert.ToByte() funcionam em uma faixa estreita de caracteres e se comportam de forma muito diferente quando a string sai dela. Encoding.GetEncoding(), por sua vez, dá acesso a codificações nomeadas, a um custo que mostramos mais adiante.
Por que converter uma string em um array de bytes em C#?
Uma string em C# é uma sequência de unidades de código UTF-16, e um array de bytes contém bytes brutos, sem nenhum significado associado. Uma codificação é a regra que transforma uma coisa na outra.
Precisamos dessa regra porque quase nada fora do nosso processo aceita uma string. Arquivos, sockets, funções de hash, APIs de criptografia e filas de mensagens, todos recebem byte[], então o texto precisa virar bytes antes de sair da aplicação.
A resposta padrão em C# é Encoding.UTF8.GetBytes(). O método aplica UTF-8 e retorna um novo array de bytes com o tamanho exato necessário.
O que importa é a codificação que escolhemos. Uma string como café gera bytes diferentes em UTF-8, ASCII, UTF-16 e Latin-1, e quem ler esses bytes depois precisa usar a mesma codificação para recuperar o texto original.
Os bytes não guardam nenhum registro da codificação que os gerou. É por isso que a codificação é uma decisão que tomamos uma vez, documentamos e aplicamos nas duas pontas, e não algo que possamos recuperar depois.
O texto não é a única fonte de bytes, claro. O mesmo array de bytes pode chegar quando os bytes vêm de um stream, ou da leitura de um arquivo diretamente para um array de bytes. Tudo o que dizemos aqui sobre codificações vale a partir do momento em que esses bytes precisam voltar a ser texto.
Sabendo disso, vejamos os vários métodos para converter uma string em um array de bytes.
Antes de começar
Para todos os exemplos de código deste artigo, vamos criar um literal de string para converter em um array de bytes:
var message = "Welcome to CodeMaze!";
Com essa string, esperamos a mesma saída para cada método de conversão:
87,101,108,99,111,109,101,32,116,111,32,67,111,100,101,77,97,122,101,33
Como Encoding.GetBytes() converte uma string?
Encoding.GetBytes() percorre a string e grava a forma codificada de cada caractere em um novo array de bytes.
O UTF-8 tem largura variável. Um caractere ASCII ocupa um byte, um caractere latino acentuado como é ocupa dois, a maioria dos caracteres CJK ocupa três e 😀 ocupa quatro. Por isso, o array de bytes costuma ser mais longo que a string, e message.Length não é o tamanho do buffer de que precisamos.
Encoding.GetByteCount() fornece esse tamanho. Encoding.GetBytes(ReadOnlySpan<char>, Span<byte>) preenche um buffer que já temos, e Encoding.TryGetBytes() faz o mesmo sem lançar exceção quando o buffer se revela pequeno demais.
Por padrão, caracteres que a codificação não consegue representar não lançam exceção. Eles são substituídos e, no caso de Encoding.ASCII, o caractere usado na substituição é um ponto de interrogação, então café volta como caf? sem exceção e sem aviso.
GetBytes() nunca grava uma marca de ordem de bytes (BOM). Os três bytes da BOM vêm de GetPreamble(), e gravá-los é responsabilidade nossa quando um consumidor espera recebê-los.
Há várias opções de codificação, e mais adiante vamos falar sobre como escolher a certa. Por enquanto, vejamos como fazer a conversão com a opção de codificação UTF8:
static byte[] ConvertStringToUTF8Bytes(string message)
{
return Encoding.UTF8.GetBytes(message);
}
Definimos um método estático e retornamos logo o array de bytes, que agora contém a string codificada. Para isso, o método usa Encoding.GetBytes(), que aplica a codificação UTF8 à variável message e converte os caracteres da string nas representações em bytes correspondentes.

E-book gratuito
Sua Web API está pronta para produção?
33 itens para verificar antes de implantá-la, com a correção de cada um. Um PDF gratuito de 76 páginas para .NET 10.
O e-book está em inglês.
Baixe o checklist gratuitoPDF gratuito. Um único e-mail para enviá-lo. Cancele a inscrição quando quiser.
Qual codificação escolher?
Escolher a codificação “certa” para converter strings em arrays de bytes depende em grande parte do contexto. Fatores como a plataforma de destino, o público, a eficiência de armazenamento e de transmissão e a interoperabilidade devem orientar nossa decisão.
| Codificação | Bytes para "café 😀" (7 caracteres) | Cobre | Use quando |
|---|---|---|---|
Encoding.UTF8 | 10 | Todo o Unicode, de 1 a 4 bytes por caractere | O padrão: web, JSON, arquivos, protocolos de rede |
Encoding.ASCII | 7, com ? no lugar de é e ?? no lugar do emoji | U+0000 a U+007F | Um consumidor legado que só aceita ASCII |
Encoding.Latin1 | 7, com é intacto e ?? no lugar do emoji | U+0000 a U+00FF | Um consumidor ISO-8859-1; é a mesma codificação que GetEncoding("ISO-8859-1") retorna |
Encoding.Unicode (UTF-16LE) | 14 | Todo o Unicode, 2 ou 4 bytes por caractere | Interoperabilidade com uma API que espera UTF-16 |
Encoding.UTF32 | 24 | Todo o Unicode, 4 bytes por caractere | Indexação de largura fixa; uso raro |
Se nenhuma codificação servir porque os bytes precisam sobreviver a uma mudança de codificação, podemos criar uma representação em bytes que não depende de codificação.
O que acontece na conversão explícita de caracteres em bytes?
A conversão explícita de caracteres em bytes oferece uma abordagem direta para converter uma string em um array de bytes, mas é fundamental conhecer suas limitações.
A conversão explícita mantém apenas o byte menos significativo de cada caractere. Os caracteres de U+0000 a U+00FF sobrevivem, então é (U+00E9) vira 233. Tudo acima disso é truncado sem erro: Ā (U+0100) vira 0, e um emoji como 😀, que o C# armazena como dois caracteres substitutos (surrogates), vira dois bytes sem relação com o original. A conversão de "café 😀" dessa forma produz 99,97,102,233,32,61,0, que, na leitura de volta, aparece como café = seguido de um byte nulo.
Vejamos como usar essa técnica na conversão:
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 um array de bytes com o mesmo tamanho da string. Isso cria um array de bytes com espaço suficiente para guardar cada caractere da string como um valor byte. Depois, iteramos por cada caractere da string, o que nos permite processar cada caractere individualmente.
Dentro do loop, atribuímos cada caractere ao índice correspondente do array de bytes. Na prática, isso converte cada caractere no valor byte subjacente e o armazena no array de bytes.
Por fim, retornamos o array de bytes preenchido. Esse array agora contém a representação em bytes da string original, em que o ponto de código de cada caractere é armazenado como um único byte, o que só é possível para os primeiros 256 pontos de código.
Quando Convert.ToByte() lança exceção em vez de converter?
Esse método faz parte da classe Convert, que oferece vários utilitários de conversão entre tipos de dados. Assim como o método anterior, ele permite converter diretamente um único caractere em seu valor byte. No entanto, ele não foi projetado para converter strings inteiras em arrays de bytes.
A conversão com essa técnica é simples:
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;
}
Embora este código tenha estrutura parecida com a do exemplo anterior, ele usa o método Convert.ToByte() para fazer a conversão de caractere em byte. Essa abordagem oferece uma forma mais explícita e potencialmente mais legível de converter caracteres nos valores byte correspondentes.
Ao contrário da conversão explícita, Convert.ToByte() se recusa a converter em vez de truncar: qualquer caractere acima de U+00FF lança uma OverflowException, o que o torna o mais seguro dos dois loops, apesar de ser o mais lento.
Quais codificações Encoding.GetEncoding() aceita?
Esse método obtém um objeto Encoding para uma codificação específica, que depois podemos usar em várias operações relacionadas a codificação, inclusive converter strings em arrays de bytes com GetBytes().
Recorremos a GetEncoding() quando algo fora do nosso controle já escolheu uma codificação por nós: uma exportação de mainframe com largura fixa, um CSV antigo, um protocolo anterior ao Unicode.
Vejamos como usar esse 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;
}
Nosso método usa uma codificação para transformar a string no array de bytes correspondente, obtendo uma instância específica da codificação ISO-8859-1 com o método Encoding.GetEncoding(). Essa codificação é fundamental para determinar como os caracteres da string são mapeados para seus valores em bytes.
Em seguida, ele calcula meticulosamente, com encoding.GetByteCount(), o número exato de bytes necessário para acomodar a string codificada e cria um array de bytes com a quantidade calculada usando new byte[].
Ele traduz os caracteres da string nos valores em bytes correspondentes e armazena os bytes codificados no array fornecido. No fim, retorna o array de bytes, agora preenchido.

E-book gratuito
Sua Web API está pronta para produção?
33 itens para verificar antes de implantá-la, com a correção de cada um. Um PDF gratuito de 76 páginas para .NET 10.
O e-book está em inglês.
Baixe o checklist gratuitoPDF gratuito. Um único e-mail para enviá-lo. Cancele a inscrição quando quiser.
Encoding.GetEncoding() só resolve as codificações que o .NET registra por padrão, uma lista curta de sete: UTF-8, UTF-16 e UTF-32 nas duas ordens de bytes, ASCII e Latin-1. ISO-8859-1 está nela, e é por isso que o código acima funciona. Páginas de código do Windows, como 1252, não estão: Encoding.GetEncoding(1252) lança uma NotSupportedException que nos pede para registrar um provedor, e Encoding.GetEncoding("windows-1252") lança uma ArgumentException, porque o nome não é um dos que ele conhece. Chamar Encoding.RegisterProvider(CodePagesEncodingProvider.Instance) uma vez na inicialização restaura todas elas.
Esse é o comportamento documentado, e não uma peculiaridade do nosso exemplo. A referência da Microsoft para Encoding.GetEncoding() diz isso diretamente: “No .NET Core, o método GetEncoding retorna as codificações com suporte nativo no .NET Core.”
Qual método de conversão é o mais rápido?
Agora que vimos vários métodos para converter uma string em um array de bytes, vamos colocá-los à prova. Vamos analisar o desempenho deles com benchmarks, começando com uma string curta e depois passando para uma mais longa.
Para a string curta, vamos usar o valor inicial de message e, para a longa, acrescentar um pouco 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.
Vejamos os benchmarks da string curta:
| 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 |
Em seguida, temos os benchmarks da string longa:
| 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 |
Nas medições com BenchmarkDotNet 0.15.8 no .NET 10, a conversão explícita de caracteres individuais continua sendo a forma mais rápida de converter uma string curta, com Convert.ToByte() tão perto que os dois se sobrepõem dentro das margens de erro. Com a string longa, a ordem se inverte: Encoding.GetBytes() é mais de duas vezes mais rápido que qualquer um dos loops, e Encoding.GetEncoding() vem logo depois. Todos os métodos alocam os mesmos 48 e 192 bytes, então a única coisa que os separa aqui é o tempo.
Qual método usar?
Encoding.UTF8.GetBytes() é a resposta, a menos que algo fora do nosso código já tenha escolhido outra codificação. Vale a pena conhecer as três alternativas principalmente pelo que elas fazem com os caracteres que não conseguem representar, e é nesse ponto que elas diferem entre si muito mais do que na velocidade.
| Método | Faixa que trata corretamente | Fora dessa faixa | Use quando |
|---|---|---|---|
Encoding.UTF8.GetBytes(s) | Todo o Unicode | Só um caractere substituto isolado, trocado por U+FFFD sem aviso | O padrão, para tudo o que sai do processo |
Encoding.ASCII.GetBytes(s) | U+0000 a U+007F | Substituído por ? (byte 63), sem aviso | O consumidor só aceita ASCII e a perda é aceitável |
Encoding.Latin1.GetBytes(s) | U+0000 a U+00FF | Substituído pelo caractere mais parecido (best-fit) ou por ? (byte 63), sem aviso: U+0100 vira A | Um consumidor ISO-8859-1 exige essa codificação |
Encoding.GetEncoding(name).GetBytes(s) | O que a codificação nomeada cobrir | O fallback da codificação, geralmente ? | Uma codificação legada nomeada é obrigatória, e o provedor está registrado |
Conversão explícita (byte)c em um loop | U+0000 a U+00FF | Truncado para o byte menos significativo, sem aviso: U+0100 vira 0 | Não recomendado |
Convert.ToByte(c) em um loop | U+0000 a U+00FF | Lança OverflowException | Caracteres isolados, quando o que queremos é uma falha explícita |
Literal "text"u8 com .ToArray() | Todo o Unicode, em tempo de compilação | Não se aplica | A string é uma constante de tempo de compilação |
Como converter um array de bytes de volta em string em C#?
Encoding.GetString() é a outra metade do par. Ele recebe um array de bytes e a mesma codificação, e pode retornar a string original.
A codificação precisa ser a mesma. Bytes gravados como UTF-8 e lidos de volta como ASCII ou Latin-1 podem produzir uma string diferente, e nada no array de bytes denuncia o erro. Por isso, a codificação viaja entre as duas pontas como um acordo, e não como dado.
Bytes que não são válidos na codificação escolhida são substituídos em vez de rejeitados. O UTF-8 transforma cada sequência inválida no caractere de substituição U+FFFD. Para que a falha seja explícita, criamos new UTF8Encoding(false, true), cujo decodificador lança uma DecoderFallbackException.
Só a ida e volta com a mesma codificação pode ser garantida. Um texto codificado em UTF-8 e decodificado em UTF-8 volta idêntico, a menos que a string contenha um caractere substituto isolado. Um texto que passa pelo ASCII perde todos os caracteres que o ASCII não consegue representar, e nenhum decodificador consegue trazê-los de volta, porque os bytes que os descreviam nunca foram gravados.
O método em si tem uma única linha:
static string ConvertUTF8BytesToString(byte[] byteArray)
{
return Encoding.UTF8.GetString(byteArray);
}
A codificação dessa linha precisa ser a mesma que gerou os bytes, e essa é a única escolha que este método faz.
Texto simples não é o único destino de um array de bytes. Podemos codificar esses bytes em Base64 para transporte, transformar o array de bytes em uma string hexadecimal para exibição ou cálculo de hash, ou fazer o caminho inverso, partindo de uma string hexadecimal. E, se os bytes vão para algum lugar não confiável, criptografar os bytes resultantes é o passo que fica entre as duas conversões.
Conclusão
Neste artigo, discutimos a importância de converter strings em arrays de bytes, vimos vários métodos de conversão e ressaltamos como é importante escolher a codificação e o método de conversão adequados ao contexto da aplicação.
Testado com .NET 10.