Como detectar automaticamente a codificação de arquivos de texto?


69

Existem muitos arquivos de texto sem formatação que foram codificados em conjuntos de caracteres variantes.

Quero convertê-los todos para UTF-8, mas antes de executar o iconv, preciso conhecer sua codificação original. A maioria dos navegadores tem uma Auto Detectopção em codificações, no entanto, não consigo verificar esses arquivos de texto um por um porque há muitos.

Depois de conhecer a codificação original, posso converter os textos por iconv -f DETECTED_CHARSET -t utf-8.

Existe algum utilitário para detectar a codificação de arquivos de texto sem formatação? NÃO precisa ser 100% perfeito, não me importo se houver 100 arquivos convertidos incorretamente em 1.000.000 de arquivos.

Respostas:


57

Experimente o módulo Python chardet , que está disponível no PyPi:

pip install chardet

Então corra chardetect myfile.txt.

O Chardet é baseado no código de detecção usado pelo Mozilla, portanto deve fornecer resultados razoáveis, desde que o texto de entrada seja longo o suficiente para análise estatística. Leia a documentação do projeto .

Conforme mencionado nos comentários, é bastante lento, mas algumas distribuições também fornecem a versão original do C ++, como o @Xavier encontrou em https://superuser.com/a/609056 . Há também uma versão Java em algum lugar.


3
Sim, e já está empacotado como python-chardetno repositório do universo Ubuntu.
Xiè Jìléi

Se não foi um palpite perfeito, chardetainda dará o palpite mais correto, como ./a.txt: GB2312 (confidence: 0.99). Comparado com o Enca, que apenas falhou e relata 'Codificação não reconhecida'. No entanto, infelizmente, chardetcorre muito devagar.
Xiè Jìléi

11
@ 谢 继 雷: Faça funcionar da noite para o dia ou algo assim. A detecção de charset é um processo complicado . Você também pode experimentar o jChardet baseado em Java ou ... o chardet original faz parte do Mozilla , mas apenas a fonte C ++ está disponível, nenhuma ferramenta de linha de comando.
grawity

2
Em relação à velocidade: a execução chardet <(head -c4000 filename.txt)foi muito mais rápida e igualmente bem-sucedida para o meu caso de uso. (no caso, não está claro esta sintaxe festa irá enviar apenas os primeiros 4000 bytes para Chardet)
ndemou

@ eu tenho chardet==3.0.4, e o nome real do executável da ferramenta de linha de comando chardetectnão é chardet.
Devy

32

Eu usaria este comando simples:

encoding=$(file -bi myfile.txt)

Ou se você deseja apenas o conjunto de caracteres real (como utf-8):

encoding=$(file -b --mime-encoding myfile.txt)

4
Infelizmente, fileapenas detecta codificações com propriedades específicas, como UTF-8 ou UTF-16. O restante - ISO8859 antigo ou seus correspondentes do MS-DOS e Windows - são listados como "8 bits desconhecidos" ou algo semelhante, mesmo para arquivos chardetdetectados com 99% de confiança.
grawity

6
arquivo me mostrou iso-8859-1
cweiske 30/03

E se a extensão estiver mentindo?
James.garriss

2
@ james.garriss: a extensão do arquivo não tem nada a ver com a codificação de conteúdo (texto).
MestreLion

29

No Linux baseado no Debian, o pacote uchardet ( Debian / Ubuntu ) fornece uma ferramenta de linha de comando. Veja abaixo a descrição do pacote:

 universal charset detection library - cli utility
 .
 uchardet is a C language binding of the original C++ implementation
 of the universal charset detection library by Mozilla.
 .
 uchardet is a encoding detector library, which takes a sequence of
 bytes in an unknown character encoding without any additional
 information, and attempts to determine the encoding of the text.
 .
 The original code of universalchardet is available at
 http://lxr.mozilla.org/seamonkey/source/extensions/universalchardet
 .
 Techniques used by universalchardet are described at
 http://www.mozilla.org/projects/intl/UniversalCharsetDetection.html

3
Obrigado! Na página inicial do projeto, não era óbvio para mim que havia uma CLI incluída. Também está disponível no OS X ao instalar uchardetvia Homebrew.
Stefan Schmidt

11
Fiquei um pouco confuso no começo porque um documento ISO 8859-1 foi falsamente identificado como Windows-1252, mas no intervalo imprimível Windows-1252 é um superconjunto da ISO 8859-1, portanto, a conversão com iconvfunciona bem.
Stefan Schmidt

16

Para Linux, existe enca e, para Solaris, você pode usar auto_ef .


O Enca parece muito rigoroso para mim: enca -d -L zh ./a.txtfalhou com a mensagem ./a.txt: Unrecognized encoding Failure reason: No clear winner.Como o @grawity mencionou, chardeté mais relaxado, porém ainda é muito lento.
Xiè Jìléi

10
O Enca falha completamente no teste "realmente faz alguma coisa".
Michael Wolf

11
O uchardet falhou (detectou o CP1252 em vez do CP1250 real), mas o encaixe funcionou bem. (single exemplo, difícil generalizar ...)
Palo


2

Voltando ao chardet (python 2.?), Essa chamada pode ser suficiente:

python -c 'import chardet,sys; print chardet.detect(sys.stdin.read())' < file
{'confidence': 0.98999999999999999, 'encoding': 'utf-8'}

Embora esteja longe de ser perfeito ...

echo "öasd" | iconv -t ISO-8859-1 | python -c 'import chardet,sys; print chardet.detect(sys.stdin.read())'
{'confidence': 0.5, 'encoding': 'windows-1252'}

2

Para aqueles que usam regularmente o Emacs, eles podem achar o seguinte útil (permite inspecionar e validar manualmente a transfomação).

Além disso, muitas vezes acho que a detecção automática de conjunto de caracteres do Emacs é muito mais eficiente do que as outras ferramentas de detecção automática de conjunto de caracteres (como chardet).

(setq paths (mapcar 'file-truename '(
 "path/to/file1"
 "path/to/file2"
 "path/to/file3"
)))

(dolist (path paths)
  (find-file path)
  (set-buffer-file-coding-system 'utf-8-unix)
  )

Então, uma simples chamada para o Emacs com este script como argumento (consulte a opção "-l") faz o trabalho.



0

isutf8(do moreutilspacote) fez o trabalho


2
Quão? Esta resposta não é realmente útil.
Moses

11
Não foi exatamente solicitado, mas é uma ferramenta útil. Se o arquivo for UTF-8 válido, o status de saída será zero. Se o arquivo não for UTF-8 válido ou houver algum erro, o status de saída será diferente de zero.
ton

0

Também no caso de você arquivar -i, você não sabe

Você pode usar este comando php que pode adivinhar o charset como abaixo:

No php você pode conferir como abaixo:

Especificando lista de codificação explicitamente:

php -r "echo 'probably : ' . mb_detect_encoding(file_get_contents('myfile.txt'), 'UTF-8, ASCII, JIS, EUC-JP, SJIS, iso-8859-1') . PHP_EOL;"

" Mb_list_encodings " mais preciso :

php -r "echo 'probably : ' . mb_detect_encoding(file_get_contents('myfile.txt'), mb_list_encodings()) . PHP_EOL;"

Aqui no primeiro exemplo, você pode ver que eu coloquei uma lista de codificações (detectar a ordem da lista) que podem estar correspondentes. Para obter resultados mais precisos, você pode usar todas as codificações possíveis em: mb_list_encodings ()

Nota As funções mb_ * requerem php-mbstring

apt-get install php-mbstring 

Consulte a resposta: https://stackoverflow.com/a/57010566/3382822

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.