Java Base64对文件进行编码并压缩

Java Base64对文件进行编码并压缩,java,encoding,base64,apache-commons-codec,Java,Encoding,Base64,Apache Commons Codec,我的目标是对文件进行编码并将其压缩到java中的文件夹中。我必须使用Apache的Commons编解码器库。我能够对它进行编码和压缩,它工作得很好,但当我将它解码回原始形式时,看起来文件还没有完全编码。看起来少了几个零件。有人能告诉我为什么会这样吗 我还附上我的代码部分供您参考,以便您可以相应地指导我 private void zip() { int BUFFER_SIZE = 4096; byte[] buffer = new byte[BUFFER_SIZE]; t

我的目标是对文件进行编码并将其压缩到java中的文件夹中。我必须使用Apache的Commons编解码器库。我能够对它进行编码和压缩,它工作得很好,但当我将它解码回原始形式时,看起来文件还没有完全编码。看起来少了几个零件。有人能告诉我为什么会这样吗

我还附上我的代码部分供您参考,以便您可以相应地指导我

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

您的主要问题是base64编码不能按块应用(尤其是apache commons实现)。这个问题越来越严重,因为您甚至不知道块有多大,因为这取决于
in.read(..)
读取的字节数

因此,您有两种选择:

  • 将完整文件加载到内存中,然后应用base64编码
  • 使用另一种基于流的Base64编码器实现(Apache Batik项目似乎包含这样的实现:)

  • BASE64编码数据通常比源数据长,但您使用源数据的长度将编码数据写入输出流

    您已使用生成数组的大小而不是变量
    len

    第二个注意事项-不要在每次编码字节时重新定义
    缓冲区。只需将结果写入输出

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

    更新:用于设置用于编码的输入缓冲区的长度。

    当您将文件内容读入缓冲区时,将获得len字节。当base64对此进行编码时,您将获得多个len字节,但仍然只向文件写入len字节。这表明读取块的最后一部分将被截断

    此外,如果读取未填满整个缓冲区,则base64编码不应超过len字节,否则在最后一个字节的填充中会出现尾随0的情况

    结合上面的信息,这意味着您必须对整个文件进行base64编码(将其全部读入一个字节[]),除非您可以保证读取的每个块都可以精确地放入base64编码的消息中。如果您的文件不是很大,我建议您阅读整个文件


    一个较小的问题是,当在循环中读取时,您可能应该检查“>-1”,而不是“>0”,但在这种情况下,这并没有什么区别

    你能提供一些示例来说明你投入了什么、得到了什么以及你希望得到什么吗?我认为这与你的问题无关,但是你的
    in.read
    测试应该是
    in.read(buffer)>-1
    ,因为这是api javadoc声明的。javadoc没有说
    0
    意味着流的结束。如果我们的心是纯洁的,我们可以在有生之年消除base64。我真的不明白为什么你要将base64编码的数据放入zip文件,但除此之外,你还有其他几个问题。读取len字节,base64对其进行编码(现在有多个len字节,然后写入len字节,因此跳过数据的最后一部分。此外,当sad未填充整个数组(例如文件的最后一部分)时您只想对实际字节进行编码,否则会得到尾随的0。@dmurali我是说,我不明白您为什么要费心对数据进行base64编码。毕竟,ZIP压缩实际上是从一种二进制格式转换为另一种二进制格式。这种编码除了更多字节和可能更差的压缩比之外,不会添加任何内容。请尝试不使用It、 嗨..现在,我又面临一个文件编码和解码的问题。当一个文件很小时,它被正确地编码和解码。但是它不支持更大的文件。例如,我的文件大小只有7.28kb,但是当我把它解码回原始形式时,只有前半部分被正确地解码,而下半部分返回给我编码的文件text back:(您认为这是因为缓冲区大小吗?我已将其指定为'byte[]encodedBuf=new byte[1024]“我想这取决于你如何解码文件。此外,我在代码中发现了另一个问题。源缓冲区的长度不是通过编码指定的。如果源文件长度不是缓冲区长度的倍数,这肯定会导致问题。现在一切正常!!!更正的代码是“byte encodedBuf[]=new byte[(int)f.length()];in.read(encodedBuf);byte enc[]=org.apache.commons.codec.binary.Base64.encodeBase64(encodedBuf);out.write(enc,0,enc.length);in.close()最后一个问题,是否可以将文件压缩到一个文件夹中,然后再进行编码?我的意思是,现在先进行编码,然后将编码后的文件压缩到一个文件夹中。但是否可以反过来进行?如果可以,你能告诉我如何进行吗?