Base64 对文件进行编码并压缩
-
13-12-2019 - |
题
我的目标是对文件进行编码并将其压缩到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(..)
读取的字节。
因此您有两个替代方案:
- 将完整文件加载到内存中,然后应用base64编码。
- 使用替代Base64编码器实现,该编码器实现基于流(Apache Batik项目似乎包含这样的实现: org.apache.batik.util.base64encoderstream )
当您将文件内容读入缓冲区时,您将获得 LEN 字节。当Base64编码此时,您可以获得超过 len 字节,但仍然只将 len 字节写入文件。读块的最后一部分将被截断。
此外,如果您的读取不填充整个缓冲区,则不应以base64编码超过 len 字节,否则您将在最后一个字节的填充中获得尾随0。
组合上面的信息意味着您必须Base64编码整个文件(将其全部读取到一个字节[]),除非您可以保证您读取的每个块可以准确地装入Base64编码的消息。如果您的文件不是很大,我建议读取整个文件。
一个较小的问题是,当在循环中读取时,你应该检查“> -1”,而不是“> 0”,但是他的情况没有差异。
不隶属于 StackOverflow