domingo, 4 de diciembre de 2011

Transformar archivos a string en java

Una vez me pasó que necesitaba llevar un archivo a través del webservice , una imagen para ser más exacto , si fuera solo texto sería sencillo abriendo el archivo y leyendo el contenido , pero en el caso de una imagen , ésta es binaria ; así que la solución sería transformar sus bytes a texto , pero qué tipo de texto ? , un tipo de hash llamado Base 64

Ahora ,  les comparto la solución :

Entorno
Sistema Operativo : Windows 7 32 bits
JDK : 1.6
Eclipse : Spring Tool Suite 2.7.1

Aquí , una vista del proyecto




Ahora el código

ArchivosUtil.java



package com.midominio.transformadorarchivos;


import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;


public class ArchivosUtil{


static int tamanioArchivo = 200; //Tamaño maximo de 200KB


public static boolean verificarExistenciaArchivo(String ruta){
File fichero = new File(ruta);
boolean sw = false;
if(fichero.exists()){
sw = true;
}
return sw;
}


public static byte[] cargarArchivoBinario(String ruta){
byte[] contenidoDelFichero = null;
   File file = new File(ruta);
   FileInputStream fis = null;
   BufferedInputStream bis = null;
   byte[] buffer = new byte[tamanioArchivo * 1024];
   int leido = 0;
   ByteArrayOutputStream bos = new ByteArrayOutputStream();


   try{
     fis = new FileInputStream(file);
     bis = new BufferedInputStream(fis);
     while ((leido = bis.read(buffer)) >= 0){
       bos.write(buffer, 0, leido);
     }
     contenidoDelFichero = bos.toByteArray();
     bos.reset();
     bos.close();
   }catch (IOException e1){
     e1.printStackTrace();   
   }finally{
     if (bis != null){
       try{
         bis.close();
       }catch (IOException e){
         e.printStackTrace();
       }
     }
   }
   return contenidoDelFichero;
}

//Crea un archivo a partir de un array de bytes
public static void crearArchivoBinario(String rutaFichero,byte[] buffer){
try{
File file = new File(rutaFichero);
file.createNewFile();
FileInputStream fileInputStream = new FileInputStream(rutaFichero);
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(buffer);
OutputStream outputStream = new FileOutputStream(rutaFichero);
int data;
while ((data = byteArrayInputStream.read()) != -1) {
outputStream.write(data);
}


fileInputStream.close();
outputStream.close();
}catch(Exception e){
e.printStackTrace();
}

}

}


Esta clase contiene las funciones para comprobar la existencia de un fichero , pasar el fichero a un array de bytes y crear un fichero en una ruta determinada a partir de un array de bytes.


NOTAS : lo de 200KB es sólo para inicializar el array de bytes


Base64Util.java



package com.midominio.transformadorarchivos;


import java.io.IOException;


import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;


public class Base64Util {


public static String convertirBytesStringBase64(byte[] buffer){
 BASE64Encoder b64 = new BASE64Encoder();
 String s = b64.encode(buffer);
 return s;
}

public static byte[] convertirStringBase64Bytes(String cadena){
BASE64Decoder b64 = new BASE64Decoder();
byte[] buf = new byte[1024];
try {
buf = b64.decodeBuffer(cadena);
} catch (IOException e) {
e.printStackTrace();
}
return buf;
}
}


Esta clase contiene las funciones para convertir un array de bytes a un string y viceversa.
Ahora que tenemos las clases , crearemos un test de JUNIT


TransformadorTest.java



package com.midominio.transformadorarchivos;


import junit.framework.TestCase;


import org.junit.After;
import org.junit.Before;
import org.junit.Test;


public class TransformadorTest extends TestCase {


String carpeta;
String archivoEntrada;
String archivoSalida;

@Before
public void setUp(){
carpeta = "C:\\prueba\\";
archivoEntrada = "fondo.jpg"; //Archivo existente
archivoSalida = "fondo-nuevo.jpg"; //Archivo que se creara
}

@After
public void tearDown(){

}

@Test
public void testTransformarArchivo(){
//Paso del archivo a string
String pathEntrada = carpeta + archivoEntrada;
boolean sw = ArchivosUtil.verificarExistenciaArchivo(pathEntrada);
assertEquals(sw,true);
byte[] bytesArchivo = ArchivosUtil.cargarArchivoBinario(pathEntrada);
String hashArchivo = Base64Util.convertirBytesStringBase64(bytesArchivo);
assertNotNull(hashArchivo);

//Paso del string a un archivo
byte[] bytesSalida = Base64Util.convertirStringBase64Bytes(hashArchivo);
String pathSalida = carpeta + archivoSalida;
ArchivosUtil.crearArchivoBinario(pathSalida, bytesSalida);
sw = ArchivosUtil.verificarExistenciaArchivo(pathSalida);
assertEquals(sw,true);
}

@Test
public void testComprobarHashArchivos(){
String path01 = carpeta + archivoEntrada;
String path02 = carpeta + archivoSalida;
byte[] bytes01 = ArchivosUtil.cargarArchivoBinario(path01);
byte[] bytes02 = ArchivosUtil.cargarArchivoBinario(path02);
String hash01 = Base64Util.convertirBytesStringBase64(bytes01);
String hash02 = Base64Util.convertirBytesStringBase64(bytes02);
assertEquals(hash01,hash02);
}
}


En el disco C: , crearemos la carpeta prueba , y adentro colocaremos nuestra imagen llamada fondo.jpg , también definiremos que el archivo que se creará cuando se haga la conversion de string a archivo , se llamará  fondo-nuevo.jpg.
En el test definimos 2 casos

  • TestTransformarArchivo : este archivo realiza la siguiente ejecución
    • Pasar el archivo fondo.jpg a un array de bytes
    • Pasar el array de bytes a un string base64
    • Pasar el string a otro array de bytes
    • Crear el archivo fondo-nuevo.jpg usando el nuevo array de bytes
    • Verificar que existe fondo-nuevo.jpg
  • TestComprobarHashArchivos : aqui usamos las 2 imagenes , las pasamos a string base64 y comparamos ambos hash ,  esto nos dará la seguridad de que no es un archivo fallado
Ejecutamos el test en junit y obtenemos el resultado :


Lo he probado con archivos pequeños de hasta algo más de 200KB , no lo he probado con archivos que pesan MB , pero no se los recomendaría , sobre todo por el tiempo de transmisión.
Espero les haya sido de utilidad , bueno aquí les dejo el código fuente


Saludos






No hay comentarios:

Publicar un comentario