Codificação de Caracteres: UTF-8 e Mojibake Explicados

Codificação de Caracteres: UTF-8 e Mojibake Explicados

O que você vai aprender

  • O que realmente significam codificação de caracteres e UTF-8, e como os termos se relacionam
  • Por que ocorre mojibake (texto embaralhado), desde os primeiros princípios
  • Um fluxo de trabalho confiável para verificar e converter codificações no Linux (file / iconv / nkf / locale)

Resumo Rápido

  • Uma codificação é um mapeamento entre caracteres e sequências de bytes. Um conjunto de caracteres (Unicode) e uma forma de codificação (UTF-8) são coisas diferentes.
  • UTF-8 é compatível com ASCII, de tamanho variável (1-4 bytes) e o padrão de fato na web e no Linux.
  • Mojibake ocorre quando a codificação usada para escrever difere da usada para ler.
  • Verifique com file -i / nkf -g; converta com iconv.

O que é Codificação de Caracteres?

Conclusão: Uma codificação de caracteres é a regra que mapeia caracteres para sequências de bytes. Computadores armazenam apenas bytes, então qualquer texto deve ser codificado para ser salvo ou transmitido.

Um computador só pode lidar com bytes (números de 0 a 255). Ele não consegue armazenar diretamente o caractere "あ" ou "A". Por isso, precisamos de uma tabela que define "qual caractere é representado por qual sequência de bytes." Isso é a codificação de caracteres.

Separar as duas camadas que são fáceis de confundir torna o entendimento do mojibake muito mais simples.

Camada Papel Exemplos
Conjunto de caracteres Atribui a cada caractere um número único (code point) Unicode, JIS X 0208
Forma de codificação Transforma code points em sequências de bytes reais UTF-8, UTF-16, Shift_JIS, EUC-JP

Por exemplo, "あ" tem o code point Unicode U+3042. Quais bytes representam U+3042 depende da forma de codificação.

Character "あ" = Unicode code point U+3042
  UTF-8  => E3 81 82      (3 bytes)
  UTF-16 => 30 42         (2 bytes)
  EUC-JP => A4 A2         (2 bytes)

Ponto-chave: O mesmo "あ" se torna bytes diferentes sob codificações diferentes. Então, se você julga erroneamente "qual codificação escreveu isso," não consegue mais transformar os bytes de volta nos caracteres corretos. Isso é exatamente o que é mojibake.

O que é UTF-8 e Por que é Dominante?

Conclusão: UTF-8 é uma forma de codificação para Unicode. Por ser compatível com ASCII, de tamanho variável e livre de problemas de ordem de bytes, tornou-se o padrão de fato na web e no Linux.

UTF-8 codifica cada caractere Unicode usando um tamanho variável de 1 a 4 bytes. Tornou-se dominante por causa dessas propriedades.

  • Compatível com ASCII: U+0000-U+007F (letras, dígitos, símbolos) usam um único byte, idêntico ao ASCII. Ferramentas existentes focadas em inglês continuam funcionando.
  • Compacto via tamanho variável: ASCII é 1 byte, caracteres como japonês são 2-3 bytes. Frequentemente menor que codificações de tamanho fixo.
  • Sem problema de ordem de bytes (endianness): Diferentemente do UTF-16, não depende de um BOM (byte order mark).
  • Auto-sincronizante: Os bits iniciais de cada byte sinalizam "byte inicial vs byte de continuação," facilitando a recuperação dos limites de caracteres mesmo no meio de um fluxo.
# Count the bytes of a string (in a UTF-8 environment)
echo -n "あ" | wc -c
3

UTF-8 e Unicode não são sinônimos. Unicode é o padrão que atribui números a caracteres; UTF-8 é uma forma de transformar esses números em bytes. "Salvar como UTF-8" é preciso, mas "salvar como Unicode" é inerentemente ambíguo.

Uma Nota sobre UTF-8 com BOM

Um arquivo UTF-8 pode começar com um BOM (os 3 bytes EF BB BF). Alguns editores do Windows o adicionam, e quando aparece no início de um shell script, #!/bin/bash não é reconhecido e a execução falha. No Linux, UTF-8 sem BOM é a norma.

Por que Ocorre Mojibake (Texto Embaralhado)?

Conclusão: Mojibake ocorre quando a codificação usada para escrever difere da usada para ler. Os bytes não estão corrompidos; apenas a regra de interpretação está incompatível.

Mojibake (o termo japonês mojibake também é amplamente usado em inglês) ocorre quando os bytes são interpretados com a codificação errada. Três casos típicos:

  1. Abrir um arquivo Shift_JIS como UTF-8 (e vice-versa)
  2. Abrir um arquivo UTF-8 como Latin-1 (ISO-8859-1) (você obtém sequências como "é")
  3. O locale do terminal não corresponde à codificação do arquivo

O ponto importante: os bytes originais estão intactos. Alinhe corretamente a regra de interpretação e, na maioria dos casos, o texto retorna.

Correct:  こんにちは        (UTF-8 bytes read as UTF-8)
Garbled:  ã"ã‚"ã«ã¡ã¯     (UTF-8 bytes read as Latin-1)

Quando você vê mojibake, antes de entrar em pânico com "o arquivo está corrompido," primeiro separe "qual codificação escreveu" de "qual codificação está lendo." Uma incompatibilidade é a causa na maioria das vezes.

Como Verificar e Converter Codificações?

Conclusão: Verifique com file -i ou nkf -g, converta com iconv. Para problemas de exibição no terminal, suspeite de locale e LANG.

Detectar a Codificação de um Arquivo

# Show the charset in MIME form
file -i notes.txt
notes.txt: text/plain; charset=utf-8

file apenas supõe, então arquivos curtos ou ambíguos podem reportar unknown-8bit. Para japonês, nkf -g (guess) é eficaz.

# Detect the Japanese encoding (nkf must be installed)
nkf -g legacy.txt
Shift_JIS

Converter Entre Codificações

iconv converte especificando a origem (-f) e o destino (-t).

# Convert from Shift_JIS to UTF-8 and save
iconv -f SHIFT_JIS -t UTF-8 legacy.txt -o utf8.txt
# List the available encodings
iconv -l

Se você especificar a codificação de origem errada, o texto já embaralhado é convertido novamente e a recuperação se torna difícil. Sempre confirme a codificação original com file -i / nkf -g primeiro, e mantenha o arquivo original.

Verificar o Terminal e o Locale

Se o arquivo em si está em UTF-8, mas ainda parece embaralhado no terminal, a configuração de locale frequentemente é a causa.

# Show the current locale
locale
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
...

Se LANG e LC_CTYPE são *.UTF-8, o terminal renderiza como UTF-8. Com C ou POSIX, texto não ASCII pode embaralhar. Para mudar temporariamente:

export LANG=en_US.UTF-8

Problemas Comuns e Soluções

Conclusão: Separe "o arquivo está correto?" de "o terminal está correto?". A maioria dos problemas é explicada por uma incompatibilidade de codificação ou uma configuração de locale.

Sintoma Causa provável Solução
Arquivo de texto inteiro está embaralhado Codificação assumida incorretamente Verifique com file -i, converta com iconv
Japonês embaralha apenas no terminal Locale não está em UTF-8 Verifique locale, defina LANG=...UTF-8
Erro no início de um script UTF-8 com BOM Remova o BOM e salve novamente
Nomes de arquivos estão embaralhados Exibido em uma codificação diferente Alinhe o locale, ou converta com convmv

Dica prática: Quando em dúvida, execute file -i primeiro. Quase sempre diz se o problema está "no lado do arquivo" ou "no lado do terminal." Criar novos arquivos como UTF-8 sem BOM causa menos acidentes.

Para experimentar echo e wc -c no terminal virtual baseado em navegador, use o terminal de aprendizado e observe os contadores de bytes você mesmo.

Resumo

Uma codificação de caracteres é uma "tabela que mapeia caracteres para bytes," e a chave para entendê-la é separar o conjunto de caracteres (Unicode) da forma de codificação (UTF-8 e afins). Mojibake não é corrupção, mas uma incompatibilidade de interpretação, então o fluxo de trabalho confiável é: confirme a codificação com file -i / nkf -g, converta com iconv, e suspeite de locale para problemas no terminal. Padronizar novos arquivos como UTF-8 sem BOM é o padrão mais seguro.