Pregunta

Mi objetivo es codificar un archivo zip en una carpeta en java.Tengo que usar el Apache Commons-biblioteca de códec.Soy capaz de codificar y comprimir y funciona bien, pero cuando me decodificar de nuevo a su forma original, parece que el archivo no ha sido completamente codificado.Se parece a un par de piezas que faltan.¿Alguien puede decirme por qué sucede esto?

Estoy adjuntando también la parte de mi código para su referencia para que usted me puede orientar 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();
    }
}
¿Fue útil?

Solución

Codificado en BASE64 de datos son generalmente más larga que la de origen, sin embargo, usted está utilizando la longitud de los datos de origen para escribir codificado para flujo de salida.

Usted tiene el uso de tamaño de la matriz en lugar de la variable len.

Segundo aviso - no redefinir buffer cada vez que codifican un byte.Simplemente escribe 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);
 }

ACTUALIZACIÓN:Uso Las matrices.copia de(...) para establecer la longitud del búfer de entrada para la codificación.

Otros consejos

Su principal problema es que la codificación base64 no se puede aplicar en el sentido de los bloques (especialmente no la implementación de Apache-Commons).Este problema está empeorando porque ni siquiera sabe lo grandes que son sus bloques, ya que esto depende de los bytes leídos por in.read(..).

Por lo tanto, tienes dos alternativas:

  1. Cargue el archivo completo a la memoria y luego aplique la codificación base64.
  2. Utilice una implementación alternativa de codificador Base64 que trabaje basada en flujo (el proyecto Apache Batik parece contener una implementación de este tipo: org.apache.batik.util.base64encoderstream )

Cuando lea el contenido del archivo en buffer obtiene len bytes.Cuando Base64 que codifica esto, obtiene más de LEN bytes, pero todavía solo escribe len bytes al archivo.Estos frijoles que la última parte de sus trozos de lectura se truncará.

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

La combinación de la información anterior Esto significa que debe basar64 codificar todo el archivo (leíelo todo en un byte []) a menos que pueda garantizar que cada trozo que lea puede caber exactamente en un mensaje codificado base64.Si sus archivos no son muy grandes, recomendaría leer todo el archivo.

Un problema más pequeño es que al leerlo en su bucle, probablemente debe verificar "> -1", no "> 0", pero en su caso no hace una diferencia.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top