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 comiconv.
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:
- Abrir um arquivo Shift_JIS como UTF-8 (e vice-versa)
- Abrir um arquivo UTF-8 como Latin-1 (ISO-8859-1) (você obtém sequências como "é")
- 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 -iounkf -g, converta comiconv. Para problemas de exibição no terminal, suspeite delocaleeLANG.
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.