是否可以组合 ZipOutputStream 和 DigestOutputstream?
Is it possible to combine a ZipOutputStream and a DigestOutputstream?
我需要先确定 .zip
文件的校验和,然后再将其上传到某处,以确保文件的完整性。
目前,我有如下内容:
for (File file : zipCandidates) {
InputStream fileInputStream = new BufferedInputStream(new FileInputStream(file));
ZipUtils.addDataToZip(zipStream, fileInputStream, file.getName());
boolean deleted = file.delete();
if (!deleted) {
log.error("Failed to delete temporary file {} : {}", file.getName(), file.getAbsolutePath());
}
}
zipStream.close();
// checksum and filesize
long fileSize = zipFile.length();
InputStream fileInputStream = FileUtils.openInputStream(zipFile);
BufferedInputStream bufferedFileInputStream = new BufferedInputStream(fileInputStream);
String checksum = DigestUtils.md5Hex(bufferedFileInputStream);
bufferedFileInputStream.close();
// upload
fileInputStream = FileUtils.openInputStream(zipFile);
bufferedFileInputStream = new BufferedInputStream(fileInputStream);
val writer = writerFactory.createWriter(blobName, fileSize, checksum);
writer.write(bufferedFileInputStream);
bufferedFileInputStream.close();
不用说,这是非常低效的,因为我必须阅读每个 .zip
文件 两次 才能在上传之前辨别其校验和。
有没有什么方法可以将上面的 ZipOutputStream
和 DigestOutputstream
结合起来,这样我就可以在写入 zip 文件时更新校验和?不幸的是,由于输出流必须是 ZipOutputStream
,我不能简单地装饰它(即 new DigestOutputStream(zipStream, digest)
)。
您当然可以构建自己的输出流来包装两个输出流(在您的特定情况下,一个是您的 ZipOutputStream,另一个是您的 DigestOutputStream)。您的新输出流实现会将它接收到的每个字节写入两个包装流。
这个用例很常见,您可能会找到满足您需求的开源版本(例如,this one from apache commons)。
Unfortunately, since the output stream has to be a ZipOutputStream
, I cannot simply decorate it (i.e. new DigestOutputStream(zipStream, digest)
).
无论如何你都不想,因为你想消化压缩操作的结果,所以你需要用[=包装DigestOutputStream
11=],换句话说:
try (ZipOutputStream zipStream = new ZipOutputStream(
new DigestOutputStream(
new FileOutputStream(zipFile),
digest))) {
// code adding zip entries here
}
String checksum = Hex.encodeHexString(digest.digest());
请注意使用 try-with-resources 以确保您的 ZipOutputStream
始终正确关闭。
我需要先确定 .zip
文件的校验和,然后再将其上传到某处,以确保文件的完整性。
目前,我有如下内容:
for (File file : zipCandidates) {
InputStream fileInputStream = new BufferedInputStream(new FileInputStream(file));
ZipUtils.addDataToZip(zipStream, fileInputStream, file.getName());
boolean deleted = file.delete();
if (!deleted) {
log.error("Failed to delete temporary file {} : {}", file.getName(), file.getAbsolutePath());
}
}
zipStream.close();
// checksum and filesize
long fileSize = zipFile.length();
InputStream fileInputStream = FileUtils.openInputStream(zipFile);
BufferedInputStream bufferedFileInputStream = new BufferedInputStream(fileInputStream);
String checksum = DigestUtils.md5Hex(bufferedFileInputStream);
bufferedFileInputStream.close();
// upload
fileInputStream = FileUtils.openInputStream(zipFile);
bufferedFileInputStream = new BufferedInputStream(fileInputStream);
val writer = writerFactory.createWriter(blobName, fileSize, checksum);
writer.write(bufferedFileInputStream);
bufferedFileInputStream.close();
不用说,这是非常低效的,因为我必须阅读每个 .zip
文件 两次 才能在上传之前辨别其校验和。
有没有什么方法可以将上面的 ZipOutputStream
和 DigestOutputstream
结合起来,这样我就可以在写入 zip 文件时更新校验和?不幸的是,由于输出流必须是 ZipOutputStream
,我不能简单地装饰它(即 new DigestOutputStream(zipStream, digest)
)。
您当然可以构建自己的输出流来包装两个输出流(在您的特定情况下,一个是您的 ZipOutputStream,另一个是您的 DigestOutputStream)。您的新输出流实现会将它接收到的每个字节写入两个包装流。
这个用例很常见,您可能会找到满足您需求的开源版本(例如,this one from apache commons)。
Unfortunately, since the output stream has to be a
ZipOutputStream
, I cannot simply decorate it (i.e.new DigestOutputStream(zipStream, digest)
).
无论如何你都不想,因为你想消化压缩操作的结果,所以你需要用[=包装DigestOutputStream
11=],换句话说:
try (ZipOutputStream zipStream = new ZipOutputStream(
new DigestOutputStream(
new FileOutputStream(zipFile),
digest))) {
// code adding zip entries here
}
String checksum = Hex.encodeHexString(digest.digest());
请注意使用 try-with-resources 以确保您的 ZipOutputStream
始终正确关闭。