Archivos, DataHandler, Base64 y otros amigos

En esta ocasión vamos a trabjar sobre el tema de archivos y la conversión a contenedores como son los DataSource y los Datahandler.
El entorno de trabajo va a ser el habitual, eclipse Juno, maven con librerias de utilidades estandar de apache y las habituales cuando se trabaja con correo/servicios web. Vaya por delante que la mayor parte de las utilidades son totalmente prescindibles y que he intentado desarrollar ejemplos que no necesiten las librerias mail/activation.
En el proyecto para hacer un pelín más cómoda la ejecución utilizo un JFileChooser para seleccionar los archivos, el volcado de archivos lo hago directamente sobre la carpeta del usuario, así me ahorro el mostrar una ventana de "Save as..." . Uso librerias de logs, log4j que bien se pueden eliminar los comentarios de logs o cambiar los "LOG" por "System.out.println". En cualquiera de los casos todo esto es accesorio para el tema que nos ocupa.

Unos apuntes breves:
  • Una forma cómoda de leer un archivo es con FileInputStream.
  • Con la librería IOUtils (IOUtils.toByteArray(objetoFileInputStream)) podemos sacar los bytes.(Apache)
  • Si es un archivo de texto podemos capturar el texto con un new String(bytes).
  • Si queremos hacer el volcado en un archivo binario utilizar FileOutputStream y sobre el hacer un write.(bytes).
  • Si lo que queremos es escribir un archivo de texto FileWriter es una opción cómoda.
Vayamos al código:
El primero es para crear un FileInjputStream a partir del FileChooser

private static FileInputStream fileInputStreamFromFileChooser(
            JFileChooser fileChooser3) {
        FileInputStream fr = null;
        try {
            fr = new FileInputStream(fileChooser3.getSelectedFile());
        } catch (FileNotFoundException e) {
            LOG.error("Uhhh, creo que no ha pillao el archivo");
        }
        return fr;
    }

Ya tenemos el FileInputStream si queremos convertirlo en un array de bytes

private static byte[] bytesFromFileInputStream(FileInputStream fr) {
        byte[] bytesLeidos = null;
        try {
            bytesLeidos = IOUtils.toByteArray(fr);
        } catch (IOException e) {
            LOG.error("Uhhh, creo que no he leido mucho");
        }
        return bytesLeidos;
    }

SI sabemos que es un texto lo que hay en el archivo podemos crear el String directamente con 

String miString= new String(arraydebytes);

 
Puede ser que queramos hacerlo de una atacada.
   

    private static byte[] byteArrayFromFile(JFileChooser fileChooser2) {
        FileInputStream fi;
        byte[] arraybytes2 = null;

        try {
            fi = new FileInputStream(fileChooser2.getSelectedFile());
            arraybytes2 = IOUtils.toByteArray(fi);
        } catch (IOException e) {
            LOG.error("Algo Chungo al sacar el array de Bytes", e);
        }
        return arraybytes2;
    } 


Si queremos obtener un dataSource a partir FileInputStream. A Partir del dataSource instanciar el dataHandler es directo.

    private static DataSource inputStreamToDataSourcer(FileInputStream fi) {
        DataSource ds2 = null;
        try {
            LOG.debug("Consiguiendo el dataHandler");
            ds2 = new ByteArrayDataSource(fi, "octet/stream");
            fi.close();
        } catch (IOException e) {
            LOG.error("Algo Chungo al sacar el dataHandler", e);
        }
        return ds2;
    }


Llegados a este punto ya sabemos como leer el archivo y meterlo en un array de bytes.
Guardar un texto en un archivo:


    private static void fromBinaryToArchiveB64(String pathMolon, String nombre,
            byte[] arraybytes) {
        try {
            LOG.debug("Debería tener ahora un array de bytes");
            byte[] resultado = Base64.encodeBase64(arraybytes);
            File newFileOne = new File(pathMolon + nombre + ".b64");
            FileWriter fw = new FileWriter(newFileOne);
            fw.write(new String(resultado));
            fw.close();
        } catch (IOException e1) {
            LOG.error("Uh,  hay algo mal", e1);
        }
    }  

Nótese que en ejemplo anterior lo que se escribe sobre el FileWriter es un texto.

Volcar el dataHandler en un archivo


 private static void fromDataHandlerToArchive(String pathMolon,
            String nombre, String extension, DataHandler dh) {
        try {
            LOG.debug("Ahora volcamos el archivo binario como copia ");
            OutputStream newFileTwo = new FileOutputStream(pathMolon + nombre
                    + "dh." + extension);
            dh.writeTo(newFileTwo);
            newFileTwo.close();
        } catch (IOException e) {
            LOG.error("Algo no ha ido bien", e);
        }
    }


    

Extraer del dataHandler el Array de Bytes


private static byte[] extractBytesFromDataHandler(DataHandler dh) {
        byte[] archivoBytes = null;

        try {
            archivoBytes = IOUtils.toByteArray(dh.getInputStream());
        } catch (IOException e2) {
            LOG.error("Algún problema al conseguir los bytes");
        }
        return archivoBytes;
    }

Volcar los bytes en un archivo:
    private static void fromBytesToArchive(String pathMolon, String nombre,
            String extension, byte[] archivoBytes) {
        try {
            LOG.debug("Ahora volcamos el archivo binario como copia ");
            FileOutputStream fw = new FileOutputStream(pathMolon + nombre
                    + "-copia." + extension);
            fw.write(archivoBytes);
            fw.close();
        } catch (IOException e) {
            LOG.error("Hay algo chungo en Salamanca");
        }
    }



En el proyecto de ejemplo hay alguna cosa más como establecer un filtro el JFileChooser...

private static FileFilter configureFileFilterTxt() {
        FileFilter filter = new FileFilter() {
            public boolean accept(File f) {
                return FilenameUtils.getExtension(f.getName())
                        .equalsIgnoreCase("txt") || f.isDirectory();
            }

            public String getDescription() {
                return "Archivos texto";
            }
        };
        return filter;
    }

Y se han empleado las librerias de apache para crear archivos codificados como Base64 y descodificar dichos archivo desde el String base 64.
Si quieres ver las dependencias aquí.
Si lo que quieres es ver el código, un poco sucio pero... en pastebin.

Como siempre lo más recomendable puede ser bajarse el proyecto completo desde aquí.

Posiblemente haga una revisión del proyecto sin dependencias y eventualmente quitando el paso a base64 de archivos binarios, ya que no me convencen nada estas librerías.