Вычислить несколько контрольных сумм из того же InputStream, используя DigestInputStream

Я пытаюсь выяснить, как читать несколько дайджестов (md5, sha1, gpg) на основе того же InputStream с помощью DigestInputStream. Из того, что я проверил в документации, это, по-видимому, возможно, клонируя дайджест. Может ли кто-нибудь проиллюстрировать это?

Я не хочу перечитывать поток, чтобы вычислить контрольные суммы.

Ответ 1

Вы можете обернуть DigestInputStream вокруг a DigestInputStream и так далее рекурсивно:

DigestInputStream shaStream = new DigestInputStream(
    inStream, MessageDigest.getInstance("SHA-1"));
DigestInputStream md5Stream = new DigestInputStream(
    shaStream, MessageDigest.getInstance("MD5"));
// VERY IMPORTANT: read from final stream since it FilterInputStream
byte[] shaDigest = shaStream.getMessageDigest().digest();
byte[] md5Digest = md5Stream.getMessageDigest().digest();

Ответ 2

Javadoc довольно ясен. Вы можете использовать клон только для вычисления различных промежуточных дайджестов с использованием того же алгоритма. Вы не можете использовать DigestInputStream для вычисления различных алгоритмов дайджеста без чтения потока несколько раз. Вы должны использовать обычные InputStream и несколько MessageDigest объектов; прочитайте данные один раз, передав каждый буфер всем объектам MessageDigest, чтобы получить несколько дайджестов с различными алгоритмами.

Вы можете легко инкапсулировать это в свой собственный вариант DigestInputStream, скажем MultipleDigestInputStream, который следует за одним общим подходом, но принимает коллекцию объектов MessageDigest или имен алгоритмов.

Pseudojava (ошибка обработки опущена)

MessageDigest sha = MessageDigest.getInstance("SHA-1");
MessageDigest md5 = MessageDigest.getInstance("MD5");
InputStream input = ...;
byte[] buffer = new byte[BUFFER_SIZE];
int len;
while((len = input.read(buffer)) >= 0)
{
    sha.update(buffer,0,len);
    md5.update(buffer,0,len);
    ...
}
byte[] shaDigest = sha.digest();
byte[] md5Digest = md5.digest();