CodeGym /Cursos /C# SELF /Problemas com encoding mismatches e

Problemas com encoding mismatches e BOM

C# SELF
Nível 37 , Lição 3
Disponível

1. Por que é tão complicado lidar com codificações?

Você já sabe que arquivos de texto — são só uma sequência de bytes. E o C# (e o .NET em geral) — é uma plataforma que quer que todas as letras apareçam no lugar certo. Pareceria que basta especificar a codificação ao ler ou gravar — e pronto. Mas o mundo real não é tão simples.

Razões para a confusão com codificações:

  • Herança histórica: Arquivos podem ser criados em diferentes sistemas operacionais e editores, cada um escolhendo sua codificação "padrão".
  • Multiplataforma: Um arquivo criado no Windows pode ser lido no Linux ou Mac, onde o "padrão" de codificação é outro.
  • BOM (Byte Order Mark): Uma "cabeçalho" especial do arquivo que às vezes está presente e às vezes não. Afeta como os programas interpretam o arquivo.

2. O que é BOM e para que serve

Resumo sobre BOM

BOM (Byte Order Mark) — é uma sequência especial de bytes no início do arquivo que diz ao programa: "Oi! Estou nesta codificação, é assim que você deve ler meus bytes".

  • BOM aparece com mais frequência em arquivos com codificações UTF-8, UTF-16 e UTF-32.
  • No UTF-8 o BOM é opcional. A presença ou ausência dele pode afetar como diferentes programas leem o arquivo.
Codificação BOM (hexadecimal) Bytes
UTF-8
EF BB BF
239 187 191
UTF-16 LE
FF FE
255 254
UTF-16 BE
FE FF
254 255
UTF-32 LE
FF FE 00 00
255 254 0 0
UTF-32 BE
00 00 FE FF
0 0 254 255

Fato curioso sobre codificações: Em ASCII e em codificações ANSI o BOM não é usado. Mas se ele aparecer por lá, vai surpreender programas antigos.

Ilustração: onde fica o BOM


+--------------------------+
| BOM |     TEXT BYTES     |
+--------------------------+
|EFBBBF|  48 65 6C 6C 6F   |  // "Hello" em UTF-8 com BOM
+--------------------------+

EF BB BF — esse é o BOM para UTF-8. Ele fica no começo do arquivo.
48 65 6C 6C 6F — são os bytes normais do texto "Hello" em UTF-8 (sem BOM ficariam exatamente iguais).
Ou seja: o arquivo começa com EF BB BF, depois vem o texto.

3. Incompatibilidade de codificações: de onde vêm os "caracteres estranhos"

Cenário típico

  1. Você grava um arquivo em UTF-8, mas sem BOM.
  2. Abre ele num editor no Windows que esperava Windows-1251 ou UTF-8 com BOM.
  3. Como resultado — em vez de "Olá, mundo!" você vê "Привет, РјРёСЂ!".

Por que isso acontece

  • O programa pensa que o arquivo está em uma codificação, mas os bytes na verdade estão em outra.
  • BOM ajuda a identificar a codificação. Mas se o BOM não existe, a "adivinhação" vira um chute. Resultado — caracteres estranhos.

Exemplos de cenários de incompatibilidade:

  • Você lê um arquivo UTF-8 como Windows-1251 — todos os símbolos não-ASCII viram abobrinha.
  • Lê um arquivo UTF-8 com BOM como "UTF-8 puro" — na maioria das vezes tudo fica ok, mas alguns programas antigos mostram caracteres estranhos no início.
  • Você grava com BOM, mas o outro software espera sem ele — o software externo pode "tropeçar".

4. Como codificação e BOM afetam trabalhar com streams

Exemplo: gravando e lendo arquivo com codificações diferentes

// Escrevemos o arquivo em UTF-8 com BOM
using var writer = new StreamWriter("test_utf8_bom.txt", false, new UTF8Encoding(true));
writer.WriteLine("Olá, mundo!");

new UTF8Encoding(true) — inclui o BOM.

// Escrevemos o arquivo em UTF-8 sem BOM
using var writer = new StreamWriter("test_utf8_no_bom.txt", false, new UTF8Encoding(false));
writer.WriteLine("Olá, mundo!");

new UTF8Encoding(false) — sem BOM.

// Leitura do arquivo com codificação especificada explicitamente
using var reader = new StreamReader("test_utf8_no_bom.txt", new UTF8Encoding(false));
string line = reader.ReadLine();
Console.WriteLine(line);

Se o arquivo está em UTF-8 sem BOM, especificar a codificação explicitamente garante a leitura correta.

Erro típico

Quando você não especifica a codificação ao ler, o StreamReader tenta adivinhar — primeiro checa o BOM, se existir; se não — usa a codificação padrão do sistema (no Windows muitas vezes é Windows-1251 para versões em russo, no Linux/Mac costuma ser UTF-8).

5. O que fazer quando há incompatibilidade de codificações

Você viu caracteres estranhos. O que fazer:

  1. Cheque em qual codificação o arquivo foi criado.
    Abra o arquivo num editor que mostre a codificação (por exemplo, Notepad++).
  2. Especifique a codificação explicitamente ao ler/gravar.
    Não confie no "padrão", mesmo que pareça que sempre funcionou:
using var reader = new StreamReader("data.txt", Encoding.UTF8);

Considere o BOM.

  • Se outro software exige BOM — adicione ele (veja new UTF8Encoding(true)).
  • Se não exige — escreva sem BOM (veja new UTF8Encoding(false)).

Exemplo: codificação errada na leitura

// Arquivo criado em UTF-8, lendo como Windows-1251
using var reader = new StreamReader("test_utf8_no_bom.txt", Encoding.GetEncoding(1251));
var text = reader.ReadToEnd();
Console.WriteLine(text); // "Olá, mundo!" ficará corrompido

6. Nuances úteis

BOM em projetos reais e em entrevistas

Se você trabalha num projeto onde precisa salvar configs, logs ou exportar dados, é bom já definir a codificação e deixar isso documentado. Pode parecer bobagem, mas quando esses arquivos são lidos por outros programas ou pessoas, mal-entendidos sobre codificação viram um monte de problemas.

Em entrevistas, o tema BOM e "símbolos estranhos no início do arquivo" é quase obrigatório. É importante não só saber o que é BOM, mas conseguir explicar por que a presença (ou ausência) dele importa para integrações e como isso se relaciona com especificar a codificação explicitamente.

Tenha cuidado ao trocar dados com sistemas externos ou com softwares em outras linguagens. Em alguns lugares o BOM é obrigatório, em outros ele quebra o parse. Se não prever isso desde o começo, vai ser difícil rastrear o problema.

Recomendações e boas práticas

  • Especifique explicitamente a codificação ao trabalhar com arquivos (nunca dependa do "padrão").
  • Se precisar de BOM — use new UTF8Encoding(true), se não — new UTF8Encoding(false).
  • Verifique arquivos em editores que suportem múltiplas codificações (por exemplo, Notepad++, Visual Studio Code).
  • Se receber um arquivo de terceiros — confirme com o colega ou na documentação qual foi a codificação usada.
  • Se precisar converter codificação ou remover o BOM — faça isso explicitamente.

O que diferentes programas veem

Arquivo Codificação de gravação Abrir como O que veremos
UTF-8 com BOM
UTF-8 + BOM
UTF-8
OK ("Olá, mundo!")
UTF-8 sem BOM
UTF-8
Windows-1251
Caracteres estranhos
Win-1251
Win-1251
UTF-8
Caracteres estranhos
UTF-8 com BOM
UTF-8 + BOM
ASCII
Os primeiros bytes ficam distorcidos

7. Como checar e remover o BOM

Exemplo: checar se há BOM

byte[] bytes = File.ReadAllBytes("test_utf8_bom.txt");
// Vamos checar os primeiros 3 bytes
if (bytes.Length >= 3 && bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF)
{
    Console.WriteLine("BOM encontrado! É UTF-8 com BOM.");
}
else
{
    Console.WriteLine("BOM ausente.");
}

Exemplo: remover o BOM (se ele estiver atrapalhando)

if (bytes.Length >= 3 && bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF)
{
    // Escrevemos o arquivo sem os primeiros 3 bytes
    File.WriteAllBytes("no_bom.txt", bytes.Skip(3).ToArray());
}

8. Erros típicos e como resolvê-los

Muitos desenvolvedores iniciantes se surpreendem quando seu programa começa a "dar problema" ao trabalhar com arquivos de texto. Normalmente o problema acontece quando o programa que escreveu o arquivo usou uma codificação (ou modo de BOM) e o programa que lê usa outra. Por exemplo, se escreveu em UTF-8 sem BOM e você lê isso no Windows cuja codificação padrão é Windows-1251, não é de se estranhar que os caracteres virem abobrinha. É extremamente importante sempre especificar a codificação explicitamente. Se o arquivo for trocado entre diferentes programas ou plataformas, use um formato universal — UTF-8 (ou UTF-8 com BOM se o software externo exigir).

Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION