Java 是否可以将ZipOutputStream和DigestOutputstream组合在一起?

Java 是否可以将ZipOutputStream和DigestOutputstream组合在一起?,java,stream,zip,checksum,Java,Stream,Zip,Checksum,我需要先确定.zip文件的校验和,然后再将其上载到某个地方,这样才能确保文件的完整性 目前,我有如下内容: for (File file : zipCandidates) { InputStream fileInputStream = new BufferedInputStream(new FileInputStream(file)); ZipUtils.addDataToZip(zipStream, fileInputStream

我需要先确定
.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)。新的输出流实现将接收到的每个字节写入两个包装流

这个用例非常常见,您可能会找到一个满足您需求的开源版本(例如)

不幸的是,由于输出流必须是
ZipOutputStream
,我不能简单地修饰它(即
newdigestOutputstream(zipStream,digest)

无论如何,您都不想这样做,因为您想对压缩操作的结果进行摘要处理,因此需要使用
ZipOutputStream
包装
DigestOutputStream
,也就是说,另一种方式:

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
始终正确关闭。

我明白了。我想我误解了
DigestOutputStream
的功能-我没有意识到
digest
会被该流变异,可以在以后阅读。谢谢。