¿Cómo Puedo Adivinar mejor la Codificación cuando Falta la BOM (Marca de Orden de Bytes)?


Mi programa tiene que leer archivos que usan varias codificaciones. Pueden ser ANSI, UTF-8 o UTF-16 (endian grande o pequeño).

Cuando la BOM (Marca de Orden de Bytes) está ahí, no tengo ningún problema. Sé si el archivo es UTF-8 o UTF-16 BE o LE.

Quería asumir cuando no había BOM que el archivo era ANSI. Pero he encontrado que los archivos con los que estoy tratando a menudo están perdiendo su lista de materiales. Por lo tanto ninguna BOM puede significar que el archivo es ANSI, UTF-8, UTF-16 BE o LE.

Cuando el archivo no tiene lista de materiales, ¿cuál sería la mejor manera de escanear parte del archivo y adivinar con mayor precisión el tipo de codificación? Me gustaría estar cerca del 100% del tiempo si el archivo es ANSI y en los 90 altos si es un formato UTF.

Estoy buscando una forma algorítmica genérica para determinar esto. Pero en realidad uso Delphi 2009 que sabe Unicode y tiene una clase TEncoding, por lo que algo específico sería un bono.


Respuesta:

La respuesta de ShreevatsaR me llevó a buscar en Google para "universal encoding detector delphi" que me sorprendió al tener este post en la lista en la posición #1 después de estar vivo por solo unos 45 minutos! Eso es googlebotting rápido!! Y también es increíble que Stackoverflow llegue al 1er lugar tan rápidamente.

La segunda entrada en Google fue una entrada de blog de Fred Eaker en Character encoding detection que enumeraba algoritmos en varios idiomas.

Encontré la mención de Delphi en esa página, y me llevó directamente a el Detector de Caracteres ChsDet Libre de Código abierto en SourceForge escrito en Delphi y basado en el componente i18n de Mozilla.

Fantástico! Gracias a todos los que respondieron (todos +1), gracias ShreevatsaR, y gracias de nuevo Stackoverflow, por ayudarme a encontrar mi respuesta en menos de una hora!

Author: lkessler, 2008-12-17

4 answers

Tal vez usted puede shell a un script de Python que utiliza Chardet: Universal Encoding Detector. Es una reimplementación de la detección de codificación de caracteres que utiliza Firefox, y es utilizada por muchas aplicaciones diferentes. Enlaces útiles: Código de Mozilla, trabajo de investigación se basó en (irónicamente, mi Firefox no detecta correctamente la codificación de esa página), breve explicación, explicación detallada .

 9
Author: ShreevatsaR,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-16 23:49:39

Aquí está cómo el bloc de notas hace eso

También existe el python Universal Encoding Detector que puede verificar.

 5
Author: Igal Serban,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-08 17:06:31

Mi conjetura es:

  • Primero, compruebe si el archivo tiene valores de bytes menores que 32 (excepto para tab/nuevas líneas). Si lo hace, no puede ser ANSI o UTF-8. Thus-UTF-16. Sólo tiene que averiguar el peso. Para esto, probablemente debería usar alguna tabla de códigos de caracteres Unicode válidos. Si encuentra códigos no válidos, pruebe la otra endianidad si eso encaja. Si encaja (o no), compruebe cuál tiene mayor porcentaje de códigos alfanuméricos. También puede probar searchung para saltos de línea y determinar el peso de ellos. Aparte de eso, no tengo ideas de cómo comprobar el endianness.
  • Si el archivo no contiene valores inferiores a 32 (aparte de dicho espacio en blanco), probablemente sea ANSI o UTF-8. Intente analizarlo como UTF-8 y vea si obtiene caracteres Unicode no válidos. Si lo haces, probablemente sea ANSI.
  • Si espera documentos en codificaciones no inglesas de un solo byte o de varios bytes que no sean Unicode, entonces no tiene suerte. Lo mejor que puedes hacer es algo como Internet Explorer que hace un histograma de valores de caracteres y lo compara con histogramas de idiomas conocidos. Funciona bastante a menudo, pero a veces falla también. Y tendrás que tener una gran biblioteca de histogramas de letras para cada idioma.
 4
Author: Vilx-,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-16 23:43:04

¿ASCII? Ningún sistema operativo moderno utiliza ASCII más. Todos usan códigos de 8 bits, al menos, lo que significa que es UTF-8, ISOLatinX, WinLatinX, MacRoman, Shift-JIS o lo que sea.

La única prueba que conozco es comprobar si hay caracteres UTF-8 no válidos. Si encuentras alguno, entonces sabes que no puede ser UTF-8. Lo mismo es probablemente posible para UTF-16. Pero cuando no hay un conjunto Unicode, entonces será difícil saber qué página de código de Windows podría ser.

La mayoría de los editores que conozco se ocupan de esto el usuario elige un valor predeterminado de la lista de todas las codificaciones posibles.

Existe código para verificar la validez de los caracteres UTF.

 1
Author: Thomas Tempelmann,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-16 23:10:07