perl utf-8 sanitization

¿Cómo desinfeto el UTF-8 no válido en Perl?



sanitization (2)

Mi programa Perl toma un texto de un archivo de disco como entrada, lo envuelve en un poco de XML y luego lo envía a STDOUT. La entrada es nominalmente UTF-8, pero a veces se ha insertado basura. Necesito desinfectar la salida de modo que no se emitan octetos UTF-8 inválidos, de lo contrario, el consumidor descendente (Sphinx) explotará.

Por lo menos, me gustaría saber si los datos son inválidos, así que puedo evitar transmitirlos; idealmente podría eliminar solo los bytes ofensivos. Sin embargo, habilitar todos los fatalismos que puedo encontrar no me lleva allí con Perl 5.12 (FWIW, use v5.12; use warnings qw( FATAL utf8 ); está en efecto).

Estoy teniendo problemas específicamente con la secuencia "/xFE/xBF/xBE" . Si creo un archivo que contenga solo estos tres bytes ( perl -e ''print "/xEF/xBF/xBE"'' > bad.txt ), intente leer el archivo con mode :encoding(UTF-8) errors out with utf8 "/xFFFE" does not map to Unicode , pero solo bajo 5.14.0. 5.12.3 y anterior son perfectamente buenas lecturas y más tarde escribir esa secuencia. No estoy seguro de dónde está obteniendo el /xFFFE (BOM inversa inverso), pero al menos tener una queja es consistente con Sphinx.

Desafortunadamente, decode_utf8("/xEF/xBF/xBE", 1) no causa errores debajo de 5.12 o 5.14. Preferiría un método de detección que no requiriera una capa de E / S codificada, ya que eso me dejará un mensaje de error y no habrá manera de desinfectar los octetos sin formato.

Estoy seguro de que hay más secuencias que debo abordar, pero solo manejar esto sería un comienzo. Entonces mis preguntas son: ¿puedo detectar de manera confiable este tipo de datos problemáticos con un perl antes de 5.14? ¿Qué rutina de sustitución generalmente puede desinfectar casi-UTF-8 en estricto UTF-8?


Deberías leer la sección UTF-8 vs. utf8 vs. UTF8 de los documentos de Encode .

Para resumir, Perl tiene dos codificaciones UTF-8 diferentes. Su codificación nativa se llama utf8 , y básicamente permite cualquier punto de código, independientemente de lo que dice el estándar Unicode sobre ese punto de código.

La otra codificación se llama utf-8 (también conocida como utf-8-strict ). Esto permite solo los puntos de código que se enumeran como legales para el intercambio por el estándar Unicode.

"/xEF/xBF/xBE" , cuando se interpreta como UTF-8, decodifica al punto de código U+FFFE . Pero eso no es legal para el intercambio de acuerdo con Unicode, por lo que los programas que son estrictos sobre tales cosas se quejan.

En lugar de usar decode_utf8 (que usa la codificación lax utf8 ), use la decode con la codificación utf-8 . Y lea la sección Manejo de Datos Malformados para ver las diferentes formas en que puede manejar o quejarse de problemas.

Actualización: parece que algunas versiones de Perl no se quejan de U + FFFE, incluso cuando usan la codificación utf-8-strict . Esto parece ser un error. Puede que tenga que crear una lista de puntos de código de los que se queja Sphinx y filtrarlos manualmente (por ejemplo, con tr ).


Tienes una cadena utf8 que contiene algunos utf8 no válidos ...

Esto lo reemplaza con un ''char malo'' predeterminado.

use Encode qw(decode encode); my $octets = decode(''UTF-8'', $malformed_utf8, Encode::FB_DEFAULT); my $good_utf8 = encode(''UTF-8'', $octets, Encode::FB_CROAK);