5

我的目标是对文件进行编码并将其压缩到 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();
    }
}
4

3 回答 3

3

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(...)设置输入缓冲区的长度以进行编码。

于 2012-03-13T09:34:55.437 回答
0

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

因此,您有两种选择:

  1. 将完整文件加载到内存中,然后应用 base64 编码。
  2. 使用基于流的替代 Base64 编码器实现(Apache Batik 项目似乎包含这样的实现:org.apache.batik.util.Base64EncoderStream
于 2012-03-13T09:32:47.523 回答
0

当您将文件内容读入缓冲区时,您将获得len个字节。当 base64 编码时,你会得到超过len个字节,但你仍然只将len个字节写入文件。您读取的块的最后一部分将被截断。

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

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

一个较小的问题是,在您的循环中阅读时,您可能应该检查“> -1”,而不是“> 0”,但在他的情况下它没有任何区别。

于 2012-03-13T09:36:55.423 回答