Можно ли объединить ZipOutputStream и DigestOutputstream? - PullRequest
1 голос
/ 11 апреля 2019

Мне нужно определить контрольную сумму файла .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)).

Ответы [ 2 ]

2 голосов
/ 11 апреля 2019

К сожалению, поскольку выходной поток должен быть ZipOutputStream, я не могу просто его украсить (т. Е. new DigestOutputStream(zipStream, digest)).

В любом случае вы не захотите, потому что вы хотите переварить результат операции архивирования, поэтому вам нужно обернуть DigestOutputStream ZipOutputStream, то есть другим способом:

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 всегда закрыт правильно.

1 голос
/ 11 апреля 2019

Вы, безусловно, можете создать собственный выходной поток, который обернет два выходных потока (в вашем конкретном случае один будет вашим ZipOutputStream, а другой - вашим DigestOutputStream).Ваша новая реализация выходного потока будет записывать каждый полученный байт в оба обернутых потока.

Этот вариант использования достаточно распространен, и вы, вероятно, найдете версию с открытым исходным кодом, которая будет отвечать вашим потребностям (например, * 1003).* это от Apache Commons ).

...