¿Cómo detectar automáticamente la codificación de archivos de texto?

69

Hay muchos archivos de texto sin formato que se codificaron en conjuntos de caracteres variantes.

Quiero convertirlos a UTF-8, pero antes de ejecutar iconv, necesito saber su codificación original. La mayoría de los navegadores tienen una Auto Detectopción en las codificaciones, sin embargo, no puedo verificar esos archivos de texto uno por uno porque hay demasiados.

Solo conociendo la codificación original, puedo convertir los textos por iconv -f DETECTED_CHARSET -t utf-8.

¿Hay alguna utilidad para detectar la codificación de archivos de texto sin formato? NO tiene que ser 100% perfecto, no me importa si hay 100 archivos mal convertidos en 1,000,000 de archivos.

Xiè Jìléi
fuente

Respuestas:

57

Pruebe el módulo chardet Python, que está disponible en PyPi:

pip install chardet

Entonces corre chardetect myfile.txt.

Chardet se basa en el código de detección utilizado por Mozilla, por lo que debe dar resultados razonables, siempre que el texto de entrada sea lo suficientemente largo para el análisis estadístico. Lea la documentación del proyecto .

Como se mencionó en los comentarios, es bastante lento, pero algunas distribuciones también incluyen la versión original de C ++ como @Xavier ha encontrado en https://superuser.com/a/609056 . También hay una versión de Java en alguna parte.

gravedad
fuente
3
Sí, y ya está empaquetado como python-chardeten el repositorio del universo de Ubuntu.
Xiè Jìléi
Si no fue una suposición perfecta, chardettodavía dará la suposición más correcta, como ./a.txt: GB2312 (confidence: 0.99). En comparación con Enca, que acaba de fallar e informa 'Codificación no reconocida'. Sin embargo, por desgracia, chardetcorre muy lento.
Xiè Jìléi
1
@ 谢 继 雷: Que funcione durante la noche o algo así. La detección de conjuntos de caracteres es un proceso complicado . También puede probar el jChardet basado en Java o ... el chardet original es parte de Mozilla , pero solo está disponible la fuente C ++, no hay una herramienta de línea de comandos.
Grawity
2
En cuanto a la velocidad: correr chardet <(head -c4000 filename.txt)fue mucho más rápido e igualmente exitoso para mi caso de uso. (en caso de que no esté claro, esta sintaxis bash enviará solo los primeros 4000 bytes a chardet)
ndemou
@ndemou que tengo chardet==3.0.4, y el nombre ejecutable real de la herramienta de línea de comando chardetectno lo es chardet.
Devy
32

Usaría este simple comando:

encoding=$(file -bi myfile.txt)

O si desea solo el conjunto de caracteres real (como utf-8):

encoding=$(file -b --mime-encoding myfile.txt)
Humpparitari
fuente
44
Desafortunadamente, filesolo detecta codificaciones con propiedades específicas, como UTF-8 o UTF-16. El resto, el antiguo ISO8859 o sus corresponsales de MS-DOS y Windows, se enumeran como "8 bits desconocidos" o algo similar, incluso para archivos que chardetdetectan con un 99% de confianza.
Grawity
66
archivo me mostró iso-8859-1
cweiske
¿Qué pasa si la extensión está mintiendo?
james.garriss
2
@ james.garriss: la extensión de archivo no tiene nada que ver con su codificación de contenido (texto).
MestreLion
29

En Linux basado en Debian, el paquete uchardet ( Debian / Ubuntu ) proporciona una herramienta de línea de comandos. Vea a continuación la descripción del paquete:

 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
Javier
fuente
3
¡Gracias! Desde la página de inicio del proyecto no era obvio para mí que había una CLI incluida. También está disponible en OS X cuando se instala a uchardettravés de Homebrew.
Stefan Schmidt
1
Al principio estaba un poco confundido porque un documento ISO 8859-1 se identificó falsamente como Windows-1252, pero en el rango de impresión Windows-1252 es un superconjunto de ISO 8859-1, por lo que la conversión iconvfunciona bien.
Stefan Schmidt
16

Para Linux, hay enca y para Solaris puede usar auto_ef .

cularis
fuente
Enca parece demasiado estricto para mí: enca -d -L zh ./a.txtfalló con el mensaje ./a.txt: Unrecognized encoding Failure reason: No clear winner.Como mencionó @grawity, chardetes más laxo, sin embargo, aún es demasiado lento.
Xiè Jìléi
10
Enca falla completamente la prueba de "realmente hace algo".
Michael Wolf
1
uchardet falló (detectó CP1252 en lugar del CP1250 real), pero enca funcionó bien. (ejemplo único, difícil de generalizar ...)
Palo
2

Volviendo a chardet (python 2.?) Esta llamada podría ser suficiente:

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

Aunque está lejos de ser perfecto ...

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
fuente
2

Para aquellos que usan Emacs regularmente, pueden encontrar útil lo siguiente (permite inspeccionar y validar manualmente la transfomación).

Además, a menudo encuentro que la autodetección de char-set de Emacs es mucho más eficiente que las otras herramientas de autodetección de char-set (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)
  )

Luego, una simple llamada a Emacs con este script como argumento (vea la opción "-l") hace el trabajo.

Yves Lhuillier
fuente
0

isutf8(del moreutilspaquete) hizo el trabajo

Ronan
fuente
2
¿Cómo? Esta respuesta no es realmente útil.
Moisés
1
No se le preguntó exactamente, pero es una herramienta útil. Si el archivo es UTF-8 válido, el estado de salida es cero. Si el archivo no es válido UTF-8, o hay algún error, el estado de salida no es cero.
ton
0

También en caso de que archives -i te da desconocido

Puede usar este comando php que puede adivinar el conjunto de caracteres como a continuación:

En php puedes marcar como a continuación:

Especificando la lista de codificación explícitamente:

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 " más precisos :

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

Aquí, en el primer ejemplo, puede ver que pongo una lista de codificaciones (detectar el orden de la lista) que podrían coincidir. Para obtener un resultado más preciso, puede usar todas las codificaciones posibles a través de: mb_list_encodings ()

Nota: las funciones mb_ * requieren php-mbstring

apt-get install php-mbstring 

Ver respuesta: https://stackoverflow.com/a/57010566/3382822

Mohamed23gharbi
fuente