Comment détecter automatiquement l'encodage de fichier texte?

69

Il existe de nombreux fichiers texte qui ont été codés dans des jeux de caractères variantes.

Je veux tous les convertir en UTF-8, mais avant d'exécuter iconv, j'ai besoin de connaître son encodage d'origine. La plupart des navigateurs ont une Auto Detectoption dans les encodages, cependant, je ne peux pas vérifier ces fichiers texte un par un car ils sont trop nombreux.

N'ayant connu que l'encodage d'origine, je peux alors convertir les textes par iconv -f DETECTED_CHARSET -t utf-8.

Existe-t-il un utilitaire permettant de détecter le codage de fichiers en texte brut? Il NE DOIT PAS être parfait à 100%, cela ne me dérange pas qu'il y ait 100 fichiers mal convertis en 1 000 000 de fichiers.

Xiè Jìléi
la source

Réponses:

57

Essayez le module chardet Python, disponible sur PyPi:

pip install chardet

Alors courez chardetect myfile.txt.

Chardet est basé sur le code de détection utilisé par Mozilla, il devrait donc donner des résultats raisonnables, à condition que le texte saisi soit suffisamment long pour permettre une analyse statistique. Lisez la documentation du projet .

Comme mentionné dans les commentaires, il est assez lent, mais certaines distributions fournissent également la version C ++ originale, comme @Xavier l’a trouvée dans https://superuser.com/a/609056 . Il existe également une version Java quelque part.

grawity
la source
3
Oui, et il est déjà packagé comme python-chardetdans le repo de l'univers Ubuntu.
Xiè Jìléi
Si ce n’était pas une hypothèse parfaite, chardetnous donnerons toujours la meilleure hypothèse, comme ./a.txt: GB2312 (confidence: 0.99). Comparé à Enca, qui vient d’échouer et qui signale un «encodage non reconnu». Malheureusement, cela chardetfonctionne très lentement.
Xiè Jìléi
1
@ 继 雷: Faites-le tourner pendant la nuit ou quelque chose comme ça. La détection de jeu de caractères est un processus compliqué . Vous pouvez également essayer jChardet ou ... basé sur Java. La chardet d' origine fait partie de Mozilla , mais seule la source C ++ est disponible, pas d'outil de ligne de commande.
Grawity
2
En ce qui concerne la vitesse: la course a chardet <(head -c4000 filename.txt)été beaucoup plus rapide et tout aussi réussie pour mon cas d'utilisation. (au cas où ce ne serait pas clair, cette syntaxe bash n'enverra que les 4000 premiers octets à chardet)
ndemou
@ndemou j'ai chardet==3.0.4, et le nom de l'exécutable réel de l'outil de ligne de commande n'est chardetectpas chardet.
Devy
32

Je voudrais utiliser cette commande simple:

encoding=$(file -bi myfile.txt)

Ou si vous voulez juste le jeu de caractères actuel (comme utf-8):

encoding=$(file -b --mime-encoding myfile.txt)
Humpparitari
la source
4
Malheureusement, fileseuls les codages dotés de propriétés spécifiques, tels que UTF-8 ou UTF-16, sont détectés. Les autres, les anciens ISO8859 ou leurs correspondants MS-DOS et Windows, sont répertoriés comme "inconnu-8 bits" ou similaire, même pour les fichiers chardetdétectés avec une confiance de 99%.
Grawity
6
dossier m'a montré iso-8859-1
cweiske
Et si l'extension est en train de mentir?
james.garriss
2
@ james.garriss: l'extension de fichier n'a rien à voir avec son codage de contenu (texte).
MestreLion
29

Sous Linux basé sur Debian, le paquet uchardet ( Debian / Ubuntu ) fournit un outil de ligne de commande. Voir ci-dessous la description du paquet:

 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
Xavier
la source
3
Merci! Sur la page d'accueil du projet, il n'était pas évident pour moi qu'il y avait une CLI incluse. Il est également disponible sur OS X lors de l'installation uchardetvia Homebrew.
Stefan Schmidt
1
J'étais un peu confus au début, car un document ISO 8859-1 était faussement identifié comme Windows-1252, mais dans la plage imprimable, Windows-1252 est un sur-ensemble d'ISO 8859-1, ce qui facilite la conversion iconv.
Stefan Schmidt
16

Pour Linux, il existe enca et pour Solaris, vous pouvez utiliser auto_ef .

cularis
la source
Enca semble trop stricte pour moi: enca -d -L zh ./a.txtéchec avec le message ./a.txt: Unrecognized encoding Failure reason: No clear winner.Comme @grawity l’a mentionné, chardetc’est plus laxiste, mais c’est pourtant trop lent.
Xiè Jìléi
10
Enca échoue complètement le test "fait réellement quelque chose".
Michael Wolf
1
uchardet a échoué (le CP1252 a été détecté au lieu du CP1250 actuel), mais l’enca a bien fonctionné. (exemple unique, difficile à généraliser ...)
Palo
2

Pour revenir à chardet (python 2.?), Cet appel pourrait suffire:

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

Bien que ce soit loin d'être parfait ....

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

Pour ceux qui utilisent régulièrement Emacs, ils pourraient trouver ce qui suit utile (permet d’inspecter et de valider manuellement la transfomation).

De plus, je trouve souvent que la détection automatique des jeux de caractères Emacs est beaucoup plus efficace que les autres outils de détection automatique des jeux de caractères (tels que 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)
  )

Ensuite, un simple appel à Emacs avec ce script en argument (voir l’option "-l") fait le travail.

Yves Lhuillier
la source
0

isutf8(de l' moreutilsemballage) a fait le travail

Ronan
la source
2
Comment? Cette réponse n'est pas vraiment utile.
Moïse
1
Ce n'est pas exactement ce qui a été demandé, mais c'est un outil utile. Si le fichier est valide UTF-8, le statut de sortie est zéro. Si le fichier n'est pas valide UTF-8 ou s'il y a une erreur, l'état de sortie est différent de zéro.
ton
0

Aussi au cas où vous classez -i vous donne inconnu

Vous pouvez utiliser cette commande php qui peut deviner un jeu de caractères comme ci-dessous:

En php, vous pouvez vérifier comme ci-dessous:

Spécifier explicitement la liste de codage:

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 " plus précis :

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

Ici, dans le premier exemple, vous pouvez voir que je mets une liste de codages (détection d’ordre de liste) pouvant correspondre. Pour obtenir un résultat plus précis, vous pouvez utiliser tous les encodages possibles via: mb_list_encodings ()

Remarque les fonctions mb_ * nécessitent php-mbstring

apt-get install php-mbstring 

Voir la réponse: https://stackoverflow.com/a/57010566/3382822

Mohamed23gharbi
la source