Frage

Mein Ziel ist es, eine Datei zu codieren und in einen Ordner in Java zu komprimieren.Ich muss die Commons-Codec-Bibliothek des Apache verwenden.Ich kann es codieren und komprimieren und es funktioniert einwandfrei, aber wenn ich es wieder in seine ursprüngliche Form dekodiere, sieht es so aus, als ob die Datei nicht vollständig codiert wurde.Sieht so aus, als ob ein paar Teile fehlen.Kann mir jemand sagen, warum das passiert?

Ich füge auch den Teil meines Codes als Referenz bei, damit Sie mich entsprechend führen können.

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();
    }
}
War es hilfreich?

Lösung

BASE64-codierte Daten sind normalerweise länger als die Quelle, Sie verwenden jedoch die Länge der Quelldaten, um codiert in den Ausgabestream zu schreiben.

Sie haben die Größe des generierten Arrays anstelle Ihrer Variablen verwendet len.

Zweiter Hinweis - nicht neu definieren buffer jedes Mal, wenn Sie ein Byte codieren.Schreiben Sie einfach das Ergebnis in die Ausgabe.

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

UPDATE:Verwenden Array.Kopie von(...) um die Länge des Eingabepuffers für die Codierung festzulegen.

Andere Tipps

Ihr Hauptproblem ist, dass die Base64-Codierung nicht blockweise angewendet werden kann (insbesondere nicht die Apache-Commons-Implementierung).Dieses Problem wird immer schlimmer, weil Sie nicht einmal wissen, wie groß Ihre Blöcke sind, da dies von den gelesenen Bytes abhängt in.read(..).

Daher haben Sie zwei Alternativen:

  1. Laden Sie die vollständige Datei in den Speicher und wenden Sie dann die Base64-Codierung an.
  2. verwenden Sie eine alternative Base64-Encoder-Implementierung, die Stream-basiert funktioniert (das Apache Batik-Projekt scheint eine solche Implementierung zu enthalten: Organisierungstafel.Apache.Batik.util.Base64EncoderStream)

Wenn Sie den Dateiinhalt in puffer lesen, erhalten Sie len bytes.Wenn Base64 codiert, erhalten Sie mehr als len bytes, aber Sie schreiben immer noch nur len bytes in die Datei.Diese Bohnen, die der letzte Teil Ihrer gelesenen Brocken abgeschnitten wird.

, wenn Ihr Lese auch den gesamten Puffer nicht füllt, sollten Sie nicht base64 codieren als len Bytes, da Sie andernfalls 0s in der Polsterung der letzten Bytes zurücklegen werden.

Die Kombination der Informationen darüber bedeutet, dass Sie base64 codieren müssen.Wenn Ihre Dateien nicht sehr groß sind, würde ich empfehlen, die gesamte Datei zu lesen.

Ein kleineres Problem ist, dass Sie beim Lesen in Ihrer Schleife wahrscheinlich für "> -1", nicht "> 0", prüfen sollten, aber int int seinen Fall, jedoch keinen Unterschied.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top