我的目标是对文件进行编码并将其压缩到java中的文件夹中。我必须使用 Apache 的 Commons-codec 库。我能够对其进行编码和压缩,并且工作正常,但是当我将其解码回原始形式时,看起来该文件尚未完全编码。看起来缺少一些零件。谁能告诉我为什么会发生这种情况?

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

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 编码数据通常比源数据长,但是您正在使用源数据的长度将编码写入输出流。

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

第二次通知 - 不要重新定义 buffer 每次编码一个字节。只需将结果写入输出即可。

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

更新:使用 Arrays.copyOf(...) 设置编码输入缓冲区的长度。

其他提示

您的主要问题是Base64编码不能应用于块(尤其不是Apache-Commons实现)。这个问题越来越糟,因为你甚至不知道你的块是多大的,这取决于in.read(..)读取的字节。

因此您有两个替代方案:

  1. 将完整文件加载到内存中,然后应用base64编码。
  2. 使用替代Base64编码器实现,该编码器实现基于流(Apache Batik项目似乎包含这样的实现: org.apache.batik.util.base64encoderstream

当您将文件内容读入缓冲区时,您将获得 LEN 字节。当Base64编码此时,您可以获得超过 len 字节,但仍然只将 len 字节写入文件。读块的最后一部分将被截断。

此外,如果您的读取不填充整个缓冲区,则不应以base64编码超过 len 字节,否则您将在最后一个字节的填充中获得尾随0。

组合上面的信息意味着您必须Base64编码整个文件(将其全部读取到一个字节[]),除非您可以保证您读取的每个块可以准确地装入Base64编码的消息。如果您的文件不是很大,我建议读取整个文件。

一个较小的问题是,当在循环中读取时,你应该检查“> -1”,而不是“> 0”,但是他的情况没有差异。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top