2008-09-22 26 views
51

Estoy procesando algunos archivos de datos que se supone que son UTF-8 válidos pero no lo son, lo que hace que el analizador (que no estoy bajo mi control) falle. Me gustaría agregar una etapa de validación previa de los datos para la formación correcta de UTF-8, pero aún no he encontrado una utilidad que me ayude a hacer esto.¿Cómo comprobar si un archivo es válido UTF-8?

Hay una web service en el W3C, que parece que está muerto, y he encontrado un sólo para Windows validación tool que los informes no válidos ficheros UTF-8, pero no informa qué líneas de caracteres y/o solucionar.

Estaría contento con una herramienta que pueda instalar y usar (idealmente multiplataforma), o una secuencia de comandos ruby ​​/ perl que pueda formar parte de mi proceso de carga de datos.

Respuesta

72

Puede usar GNU iconv:

$ iconv -f UTF-8 your_file -o /dev/null 

O con versiones anteriores de iconv, como en MacOS:

$ iconv -f UTF-8 your_file > /dev/null; echo $? 

El comando devolverá 0 si el archivo se puede convertir con éxito, y 1 si no Además, imprimirá la compensación de bytes donde se produjo la secuencia de bytes no válidos.

Editar: La codificación de salida no tiene que especificarse, se supondrá que es UTF-8.

+13

En las versiones anteriores de iconv, como la de OSX o en fink, no hay indicador -o. Sin embargo, redireccionar la salida estándar siempre debería funcionar. –

+1

Torsten, gracias esto funciona perfectamente en mi máquina Linux. No pude encontrar una versión de la utilidad iconv para cygwin, pero eso no es sorprendente. –

+2

no detecta todos los problemas ... – zvolkov

10

Utilice las funciones python y str.encode | decode.

>>> a="γεια" 
>>> a 
'\xce\xb3\xce\xb5\xce\xb9\xce\xb1' 
>>> b='\xce\xb3\xce\xb5\xce\xb9\xff\xb1' # note second-to-last char changed 
>>> print b.decode("utf_8") 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/local/lib/python2.5/encodings/utf_8.py", line 16, in decode 
    return codecs.utf_8_decode(input, errors, True) 
UnicodeDecodeError: 'utf8' codec can't decode byte 0xff in position 6: unexpected code byte 

La excepción arrojada tiene la información solicitada en su propiedad .args.

>>> try: print b.decode("utf_8") 
... except UnicodeDecodeError, exc: pass 
... 
>>> exc 
UnicodeDecodeError('utf8', '\xce\xb3\xce\xb5\xce\xb9\xff\xb1', 6, 7, 'unexpected code byte') 
>>> exc.args 
('utf8', '\xce\xb3\xce\xb5\xce\xb9\xff\xb1', 6, 7, 'unexpected code byte') 
3

¿Qué tal la biblioteca gnu iconv? Usando la función iconv(): "Se encuentra una secuencia multibyte no válida en la entrada. En este caso, establece errno en EILSEQ y devuelve (size_t) (- 1). * Inbuf queda apuntando al comienzo de la secuencia multibyte no válida. "

EDITAR: oh - me perdí la parte en la que desea un lenguaje de scripting. Pero para el trabajo de línea de comandos, la utilidad iconv también debe validar para usted.

-3

El siguiente código C++ se basa en uno publicado en muchos sitios a través de Internet. Corregí el error en el código original y agregué la posibilidad de recuperar tanto la posición del carácter no válido como el carácter no válido.

///Returns -1 if string is valid. Invalid character is put to ch. 
int getInvalidUtf8SymbolPosition(const unsigned char *input, unsigned char &ch) { 
    int     nb, na; 
    const unsigned char *c = input; 

    for (c = input; *c; c += (nb + 1)) { 
    if (!(*c & 0x80)) 
     nb = 0; 
    else if ((*c & 0xc0) == 0x80) 
    { 
     ch = *c; 
     return (int)c - (int)input; 
    } 
    else if ((*c & 0xe0) == 0xc0) 
     nb = 1; 
    else if ((*c & 0xf0) == 0xe0) 
     nb = 2; 
    else if ((*c & 0xf8) == 0xf0) 
     nb = 3; 
    else if ((*c & 0xfc) == 0xf8) 
     nb = 4; 
    else if ((*c & 0xfe) == 0xfc) 
     nb = 5; 
    na = nb; 
    while (na-- > 0) 
     if ((*(c + nb) & 0xc0) != 0x80) 
     { 
      ch = *(c + nb); 
      return (int)(c + nb) - (int)input; 
     } 
    } 

    return -1; 
} 
+3

No reutilice este código, acepta UTF-8 mal formado, como representaciones de formas no más cortas, sustitutos y puntos de código codificados por encima del espacio de códigos Unicode (U + 10FFFF). – chansen

+0

chansen, ¿son representaciones de formas no más cortas y sustitutos prohibidos en UTF-8 válido? Pensé que contienen símbolos UTF-8 válidos de tal manera que, por ejemplo, MSXML4.0 cargará XML codificado en UTF-8 con tales símbolos sin errores. – izogfif

+0

izogfif, [La versión estándar Unicode 6.1] (http://www.unicode.org/versions/Unicode6.1.0/) - [3.9 Formas de codificación Unicode] (http://www.unicode.org/versions/Unicode6. 1.0/ch03.pdf) - UTF-8 D92: "Antes del estándar Unicode, versión 3.1, las secuencias de bytes problemáticas de" forma no más corta "en UTF-8 eran aquellas en las que los caracteres BMP podían representarse de más de una manera. las secuencias están mal formadas, porque no están permitidas en la Tabla 3-7 ". "Debido a que los puntos de código sustituto no son valores escalares Unicode, cualquier secuencia de bytes UTF-8 que de otra manera se correlacionaría con los puntos de código D800..DFFF está mal formada". – chansen

4

Puede utilizar isutf8 de la colección moreutils.

$ apt-get install moreutils 
$ isutf8 your_file 

En un script de shell, utilice el interruptor --quiet y comprobar el estado de salida, que es cero para los archivos que son UTF-8 válidos.

+0

para mac os "brew install moreutils". https://rentes.github.io/unix/utilities/2015/07/27/moreutils-package/ – Oshanz

Cuestiones relacionadas