2012-03-13 16 views
5

Mi objetivo es codificar un archivo y comprimirlo en una carpeta en java. Tengo que usar la biblioteca Apache's Commons-codec. Puedo codificar y comprimirlo y funciona bien, pero cuando lo decodifico de nuevo a su forma original, parece que el archivo no se ha codificado por completo. Parece que faltan algunas partes. ¿Alguien puede decirme por qué sucede esto?Base64-codificar un archivo y comprimirlo

También estoy adjuntando la parte de mi código como referencia para que pueda guiarme en consecuencia.

private void zip() { 
    int BUFFER_SIZE = 4096; 
    byte[] buffer = new byte[BUFFER_SIZE]; 

    try { 
     // Create the ZIP file 
     String outFilename = "H:\\OUTPUT.zip"; 
     ZipOutputStream out = new ZipOutputStream(new FileOutputStream(
       outFilename)); 

     // Compress the files 
     for (int i : list.getSelectedIndices()) { 
      System.out.println(vector.elementAt(i)); 
      FileInputStream in = new FileInputStream(vector.elementAt(i)); 
      File f = vector.elementAt(i); 

      // Add ZIP entry to output stream. 
      out.putNextEntry(new ZipEntry(f.getName())); 

      // Transfer bytes from the file to the ZIP file 
      int len; 

      while ((len = in.read(buffer)) > 0) { 
       buffer = org.apache.commons.codec.binary.Base64 
         .encodeBase64(buffer); 
       out.write(buffer, 0, len); 

      } 

      // Complete the entry 
      out.closeEntry(); 
      in.close(); 

     } 

     // Complete the ZIP file 
     out.close(); 
    } catch (IOException e) { 
     System.out.println("caught exception"); 
     e.printStackTrace(); 
    } 
} 
+0

¿Puede proporcionar algunas muestras que muestren lo que puso, lo que salió y lo que esperaba obtener? – Anonymoose

+0

No creo que tenga nada que ver con su problema, pero su prueba 'in.read' probablemente debería ser' in.read (buffer)} -1', ya que eso es lo que indica el api javadoc. Javadoc no dice que '0' significa fin de secuencia. http://docs.oracle.com/javase/1.4.2/docs/api/java/io/InputStream.html # read% 28byte []% 29 –

+1

Si nuestros corazones son puros, podemos eliminar a base64 en nuestra vida. –

Respuesta

3

de datos codificada en base64 son generalmente más largo que la fuente, sin embargo, está utilizando la longitud de los datos de origen para escribir codificados en la secuencia de salida.

Tiene el tamaño de la matriz generada en lugar de su variable len.

Segundo aviso: no redefina buffer cada vez que codifique un byte. Simplemente escriba el resultado en la salida.

while ((len = in.read(buffer)) > 0) {       
    byte [] enc = Base64.encodeBase64(Arrays.copyOf(buffer, len)); 
    out.write(enc, 0, enc.length); 
} 

UPDATE: Uso Arrays.copyOf(...) para ajustar la longitud de la memoria intermedia de entrada para la codificación.

+0

¡¡¡Impresionante ... !! ¡¡Gracias!! ¡Funciona! – dmurali

+0

HI ... Ahora, de nuevo me enfrenta un problema al codificar y decodificar un archivo. Cuando un archivo es realmente pequeño, se codifica n decodificado correctamente. Pero no admite archivos más grandes. Por ejemplo; el tamaño de mi archivo es de solo 7.28kb, pero cuando lo decodifico de nuevo a la forma original, solo la primera mitad se decodifica correctamente, mientras que la siguiente mitad me devuelve el texto codificado :(¿Crees que esto se debe al tamaño del búfer? ? Lo he especificado como 'byte [] encodedBuf = new byte [1024];' – dmurali

+0

Supongo que depende de cómo decodifique el archivo. Además, he encontrado otro problema en el código. La longitud del buffer de origen no está especificada por codificación. Esto definitivamente causará problemas si la longitud de un archivo fuente no es un múltiplo de la longitud del buffer. – DRCB

0

Su principal problema es que la codificación base64 no se puede aplicar por bloques (sobre todo no la implementación Apache-commons). Este problema empeora porque ni siquiera sabe qué tan grandes son sus bloques, ya que esto depende de los bytes leídos por in.read(..).

Por lo tanto, tienen dos alternativas:

  1. cargar el archivo completo en la memoria y luego aplicar la codificación base64.
  2. utiliza una implementación codificador Base64 alternativa que funciona basada en secuencias (el proyecto Apache Batik parece contener dicha implementación: org.apache.batik.util.Base64EncoderStream)
0

Cuando lee el contenido del archivo en buffer obtiene len bytes. Cuando base64 codifica esto obtienes más de len bytes, pero solo escribes len bytes en el archivo. Estos beans que la última parte de sus fragmentos de lectura se truncarán.

Además, si su lectura no llena todo el búfer, no debe base64 codificar más de len bytes, ya que de lo contrario obtendrá 0s finales en el relleno de los últimos bytes.

Combinando la información anterior, esto significa que debe codificar64 todo el archivo (léelo todo en un byte []) a menos que pueda garantizar que cada fragmento que lea pueda caber exactamente en un mensaje codificado en base64. Si sus archivos no son muy grandes, le recomendaría leer todo el archivo.

Un problema menor es que al leer en su ciclo, probablemente debería comprobar "> -1", no "> 0", pero en su caso no hace la diferencia.

Cuestiones relacionadas