2009-11-04 12 views
31

Dado un conjunto de bytes que representan texto en una codificación desconocida (generalmente UTF-8 o ISO-8859-1, pero no necesariamente), ¿cuál es la mejor manera de obtener una estimación de la codificación más probable utilizada (en Java)?Adivinar la codificación del texto representado como byte [] en Java

Vale la pena destacar:

  • No se meta-datos adicionales están disponibles. La matriz de bytes es literalmente la única entrada disponible.
  • El algoritmo de detección obviamente no será 100% correcto. Si el algoritmo es correcto en más del 80% de los casos, eso es suficiente.
+2

http://stackoverflow.com/questions/373081/ tal vez de ayuda – Chris

Respuesta

28

El siguiente método resuelve el problema usando juniversalchardet, que es un puerto Java de la biblioteca de detección de codificación de Mozilla.

public static String guessEncoding(byte[] bytes) { 
    String DEFAULT_ENCODING = "UTF-8"; 
    org.mozilla.universalchardet.UniversalDetector detector = 
     new org.mozilla.universalchardet.UniversalDetector(null); 
    detector.handleData(bytes, 0, bytes.length); 
    detector.dataEnd(); 
    String encoding = detector.getDetectedCharset(); 
    detector.reset(); 
    if (encoding == null) { 
     encoding = DEFAULT_ENCODING; 
    } 
    return encoding; 
} 

El código de arriba se ha probado y funciona de la manera prevista. Simplemente agregue juniversalchardet-1.0.3.jar al classpath.

He probado tanto juniversalchardet como jchardet. Mi impresión general es que juniversalchardet proporciona la mejor precisión de detección y la mejor API de las dos bibliotecas.

+0

mi requisito de proyecto es si los datos no están en utf8 (después de la detección) y luego conviértelos a utf8, ¿cómo hacer esto? –

+0

@coding_idiot utiliza la codificación "adivinada" para convertir a una Cadena y luego obtiene los bytes utf-8: 'new String (bytes, adivinadoEncoding) .getBytes (" utf-8 ")'. –

+0

Ahora el proyecto está en [github] (https://github.com/albfernandez/juniversalchardet) – bigspawn

0

Salida jchardet

+7

Por favor, elabore: ¿por qué considera que jchardet es la mejor biblioteca? – knorv

+0

@chi cómo convertir a utf8 si la codificación no es utf8. –

-1

En caso de haber material ya disponible

Google búsqueda permitió icu4j

o

http://jchardet.sourceforge.net/

+2

Yo sé cómo usar Google, pero la pregunta específicamente pregunta "¿cuál es la mejor manera [..]". Entonces, ¿cuál es mejor, icu4j, jchardet o alguna otra biblioteca? – knorv

1

respuesta de Chi parece más prometedora para su uso real. Sólo quiero añadir que, de acuerdo con Joel Spolsky, Internet Explorer utilizado un algoritmo de adivinanzas basado en la frecuencia en su día:

http://www.joelonsoftware.com/articles/Unicode.html

En términos generales, toda la supuesta-a-ser-texto se copia, y analizado en cada codificación imaginable. Cualquiera que sea el parse que mejor se ajuste al perfil de frecuencia de una palabra (y una letra) de un idioma, gana. No puedo ver rápidamente si jchardet usa el mismo tipo de enfoque, así que pensé en mencionarlo por si acaso.

-1

Sin indicador de codificación, nunca se sabrá con certeza. Sin embargo, puedes hacer algunas conjeturas inteligentes. Véase mi respuesta a esta pregunta,

How to determine if a String contains invalid encoded characters

utilizar los métodos validUTF8(). Si devuelve verdadero, trátelo como UTF8, de lo contrario como Latin-1.

+0

¿Qué pasa con los casos en que no es UTF-8? – knorv

+0

Si no es UTF-8, llamarlo ciegamente Latin-1 no es una buena idea. Sería mejor usar ICU, jchardet o alguna de las otras herramientas enumeradas en esta página para hacer una suposición inteligente. –

3

Aquí es mi favorita: http://glaforge.free.fr/wiki/index.php?wiki=GuessEncoding

Funciona así:

  • Si hay un UTF-8 o UTF-16 BOM, regresa esa codificación.
  • Si ninguno de los bytes tiene el bit de orden alto establecido, devuelva ASCII (o puede forzarlo a devolver una codificación predeterminada de 8 bits en su lugar).
  • Si hay bytes con el conjunto de bits alto pero están organizados en los patrones correctos para UTF-8, devuelva UTF-8.
  • De lo contrario, devuelva la codificación predeterminada de la plataforma (por ejemplo, windows-1252 en un sistema Windows de configuración regional en inglés).

Puede sonar excesivamente simplista, pero en mi trabajo diario es más del 90% de precisión.

Cuestiones relacionadas