¿Cómo detectar secuencias de bytes UTF-8 ilegales para reemplazarlas en el flujo de entrada java?
encoding inputstream (3)
El comportamiento que desea ya es el predeterminado para InputStreamReader
. Así que no hay necesidad de especificarlo usted mismo. Esto basta:
final BufferedInputStream in = new BufferedInputStream(istream);
final Reader inputReader = new InputStreamReader(in, StandardCharsets.UTF_8);
El archivo en cuestión no está bajo mi control. La mayoría de las secuencias de bytes son válidas en UTF-8, no es ISO-8859-1 (u otra codificación). Quiero hacer mi mejor esfuerzo para extraer la mayor cantidad de información posible.
El archivo contiene algunas secuencias de bytes ilegales, que deben reemplazarse con el carácter de reemplazo.
No es una tarea fácil, cree que requiere cierto conocimiento sobre la máquina de estados UTF-8.
Oracle tiene una envoltura que hace lo que necesito:
UTF8ValidationFilter javadoc
¿Hay algo así disponible (comercialmente o como software libre)?
Gracias
-stephan
Solución:
final BufferedInputStream in = new BufferedInputStream(istream);
final CharsetDecoder charsetDecoder = StandardCharsets.UTF_8.newDecoder();
charsetDecoder.onMalformedInput(CodingErrorAction.REPLACE);
charsetDecoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
final Reader inputReader = new InputStreamReader(in, charsetDecoder);
Una forma sería leer los primeros bytes para verificar la marca de orden de bytes (si existe). Más información sobre la lista de materiales: http://en.wikipedia.org/wiki/Byte_order_mark En la url dada, encontrará una tabla de los bytes de la lista de materiales. Sin embargo, un problema es que UTF-8 no requiere usar BOM en su encabezado. Hay otra manera de resolver el problema es mediante el reconocimiento de patrones (lea cada vez algunos bytes-8 bits). De todos modos, esta es la solución complicada.
java.nio.charset.CharsetDecoder hace lo que necesita. Esta clase proporciona la decodificación de conjuntos de caracteres con acciones definibles por el usuario en diferentes tipos de errores (ver onMalformedInput()
y onUnmappableCharacter()
).
CharsetDecoder
escribe en un OutputStream
, que puede canalizar en un InputStream
usando java.io.PipedOutputStream
, creando efectivamente un InputStream
filtrado.