Domanda

Il mio obiettivo è di codificare un file e cernarlo in una cartella in Java.Devo usare la libreria Codec Commons-Codec di Apache.Sono in grado di codificarlo e cerchiare e funziona bene, ma quando la decodifico nella sua forma originale, sembra che il file non sia stato completamente codificato.Sembra che alcune parti manchi.Qualcuno può dirmi perché questo accade?

Sto anche allegando la parte del mio codice per il tuo riferimento in modo da poter guidarmi di conseguenza.

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();
    }
}
.

È stato utile?

Soluzione

Base64 I dati codificati sono generalmente più lunghi di origine, tuttavia si utilizza la lunghezza dei dati di origine per scrivere codificati in flusso di uscita.

Hai usato la dimensione dell'array generato invece della tua variabile len.

Secondo preavviso - Non ridefinire buffer ogni volta che si codifica un byte.Basta scrivere il risultato in output.

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

Aggiornamento: utilizzare arrays.copyof (...) per impostare la lunghezza del buffer di ingresso per la codifica.

Altri suggerimenti

Il tuo problema principale è che la codifica di base64 non può essere applicata a blocco (specialmente non l'implementazione di Apache-Commons).Questo problema è peggiore perché non sai nemmeno quanto siano grandi i tuoi blocchi come questo dipende dai byte letti da in.read(..).

Pertanto hai due alternative:

    .
  1. Carica il file completo in memoria e quindi applicare la codifica BASE64.
  2. Utilizzare un'immentazione di Encoder Base64 alternativa che funziona in base a streaming (il progetto Apache Batik sembra contenere tale implementazione: org.apache.batik.util.base64encoderstream )

Quando si legge il contenuto del file in buffer ottieni len bytes.Quando Base64 codifica questo si ottiene più di len bytes, ma si scrive ancora len bytes al file.Questo fagiolo che l'ultima parte dei tuoi pezzi di lettura verrà troncata.

Anche, se la lettura non riempia l'intero buffer che non si dovrebbe basare64 codificare più di Len Bytes poiché altrimenti riceverai il training 0s nell'imbottitura degli ultimi byte.

Combinando le informazioni di cui sopra questo significa che è necessario basare64 codificare l'intero file (leggi tutto in un byte []) a meno che tu non sia possibile garantire che ogni pezzo che hai letto può adattarsi esattamente in un messaggio codificato BASE64.Se i tuoi file non sono molto grandi, consiglierei di leggere l'intero file.

Un problema più piccolo è che quando si legge nel tuo loop dovresti probabilmente controllare "> -1", non "> 0", ma int caso non fa la differenza.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top