Problemas de encoding en XML

En alguna ocasión me he encontrado problemas con el encoding de los archivos o de los xml que me llegan. Al final de la entrada la solución para cuando nos llega un xml, con un archivo es lo mismo con un encoding ISO-8859-1.

Generación de los XML:
Para generar unos xml vamos a utilizar la posibilidad de crear un xml a partir de un properties. Generaremos dos, uno como UTF-8 y otro como ISO-8859-1.

A partir del mismo properties, lo salvamos con:

FileOutputStream fo;
        try {
            fo = new FileOutputStream(fileutf);
            propertiesOrigen.storeToXML(fo, "Cómo mola UTF-8", "UTF-8");
            fo = new FileOutputStream(fileiso);
            propertiesOrigen.storeToXML(fo, "Cómo mola ISO", "ISO-8859-1");
        } catch (Exception e) {
            e.printStackTrace();
        }

Puedes abrirlo con tu editor favorito y comprobarás que los guarda correctamente, con el encoding indicado.

Si los lees a través del método que proporciona el objeto properties todo es correcto:

        InputStream input = new FileInputStream(fileutf);
            propertiesUTF8.loadFromXML(input);
            input.close();
            System.out.println("Propiedad uno UTF "
                    + propertiesUTF8.getProperty("valor1"));
            Properties propertiesISO = new Properties();
            is = new FileInputStream(fileutf);
            propertiesISO.loadFromXML(is);
            is.close();
            System.out.println("Propiedad uno ISO "
                    + propertiesISO.getProperty("valor1"));



Una vez confirmado que generamos archivo con el encoding deseado y "controlado" vamos a leer esos archivos con un código de lectura "standar":

            FileReader fr = new FileReader(fileutf);
            BufferedReader br = new BufferedReader(fr);
            StringWriter sw = new StringWriter();
            String currentLine = br.readLine();
            while (currentLine != null) {
                sw.append(currentLine);
                currentLine = br.readLine();
            }
            System.out.println("Lectura " + sw.toString());


Esto nos funciona muy bien con el archivo UTF-8, pero no con el archivo ISO. La razón es que no interpreta que el array de bytes corresponde a una codificación ISO-8859-1. Asume que es un UTF-8 y nos la lia parda. :-)

Pero en ese código no hay manera (o yo no sé) de indicarle que lo que está leyendo corresponde a un string no codificado "standar".

La solución pasa por "dar un rodeo" e indicarle que tome un StreamReader con el Charset empleado para codificar el contenido:

    InputStream fis = new FileInputStream(fileiso);
            InputStreamReader isr = new InputStreamReader(fis,
                    Charset.forName("ISO-8859-1"));
            BufferedReader br = new BufferedReader(isr);
            StringWriter stringWriter = new StringWriter();
            String currentLine = br.readLine();
            while (currentLine != null) {
                stringWriter.append(currentLine);
                currentLine = br.readLine();
            }
            System.out.println("Lectura Buena " + stringWriter.toString());


Ahora el stringWriter ya tiene el contenido correcto.

Como lo mejor es verlo completo y en ejecucción ( atento al path donde guardo/leo los archivos) dejo la clase completa en pastebin.
Por supuesto que lo mejor es que nos llegue directamente como UTF-8, pero si  no podemos controlarlo tener manejar como objeto intermedio un inputStream  puede ser la solución.

Queda iniciada esta nueva temporada en este blog, en la que iré añadiendo snippset de esas cosas curiosas que te vas encontrando.


Comentarios