Pergunta

Meu objetivo é codificar um arquivo e zip em uma pasta em java.Eu tenho que usar o Apache Commons-codec library.Eu sou capaz de codificar e zip-lo e ele funciona bem, mas quando eu decodificá-la de volta para sua forma original, parece que o arquivo não tenha sido completamente codificada.Parece que algumas partes estão faltando.Alguém pode me dizer por que isso acontece?

Eu também estou anexando parte do meu código para sua referência, de modo que você pode me orientar adequadamente.

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();
    }
}
Foi útil?

Solução

BASE64 encoded dados são, normalmente, mais de uma fonte, no entanto, você está usando o comprimento de dados de origem para escrever codificada para o fluxo de saída.

Você tem o direito de usar tamanho da matriz gerada em vez da variável len.

Segundo aviso - não redefinir buffer a cada vez que você codificar um byte.Basta escrever o resultado na saída.

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

ATUALIZAÇÃO:Utilização Matrizes.copyOf(...) para definir o tamanho do buffer de entrada para a codificação.

Outras dicas

Seu principal problema é que a codificação base64, não pode ser aplicado bloco-sábio (especialmente o apache-commons implementação).Esse problema está ficando pior, porque você não sabe mesmo grandes como os blocos são como este depende de bytes lidos por in.read(..).

Portanto, você tem duas alternativas:

  1. Carregar o arquivo completo para a memória e, em seguida, aplicar a codificação base64.
  2. use uma alternativa Base64 codificador de implementação que funciona baseado em fluxo (o Apache Batik projeto parece conter como uma aplicação: org.apache.batik.util.Base64EncoderStream)

Quando você ler o conteúdo do arquivo em memória intermédia você começa len bytes.Quando a codificação base64 isso, você ganha mais do que len bytes, mas você ainda é só escrever len bytes para o arquivo.Esse feijão que a última parte de sua trechos de leitura será truncado.

Também, se a sua leitura não preencher todo o buffer que você não deve base64 codificar mais do que len bytes como caso contrário você vai começar à direita 0s no preenchimento dos últimos bytes.

Combinando as informações acima, isso significa que você deve base64 codificar o arquivo inteiro (leia-o em um byte []), a menos que você pode garantir que cada pedaço de você ler pode caber exatamente em uma mensagem codificada em base64.Se os seus arquivos não são muito grande, que eu recomendaria a leitura de todo o arquivo.

Um pequeno problema é que ao ler em seu loop, você provavelmente deve verificar "> -1", não "> 0", mas int seu caso, não faz diferença.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top