Bardzo wolno generować MD5 dla dużych plików przy użyciu Javy

Używam Javy do generowania skrótu MD5 dla niektórych plików. Muszę wygenerować jeden MD5 dla kilku plików o łącznym rozmiarze około 1 gigabajta. Oto Mój kod:

private String generateMD5(SequenceInputStream inputStream){
    if(inputStream==null){
        return null;
    }
    MessageDigest md;
    try {
        int read =0;
        byte[] buf = new byte[2048];
        md = MessageDigest.getInstance("MD5");
        while((read = inputStream.read(buf))>0){
            md.update(buf,0,read);
        }
        byte[] hashValue = md.digest();
        return new String(hashValue);
    } catch (NoSuchAlgorithmException e) {
        return null;
    } catch (IOException e) {
        return null;
    }finally{
        try {
            if(inputStream!=null)inputStream.close();
        } catch (IOException e) {
            // ...
        }
    } 

}

To chyba trwa wiecznie. Jak mogę uczynić go bardziej wydajnym?
Author: Jesse Glick, 2012-02-17

3 answers

Możesz skorzystać z biblioteki Fast MD5 . Jest znacznie szybszy niż wbudowany w Javę dostawca MD5, a uzyskanie hasha jest tak proste, jak:

String hash = MD5.asHex(MD5.getHash(new File(filename)));

Należy pamiętać, że powolna prędkość może być również spowodowana powolnym wejściem/wyjściem plików.

 18
Author: Sticky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-17 02:08:13

Przepisuję Twój kod za pomocą nio, kod jest trochę jak poniżej:

private static String generateMD5(FileInputStream inputStream){
    if(inputStream==null){

        return null;
    }
    MessageDigest md;
    try {
        md = MessageDigest.getInstance("MD5");
        FileChannel channel = inputStream.getChannel();
        ByteBuffer buff = ByteBuffer.allocate(2048);
        while(channel.read(buff) != -1)
        {
            buff.flip();
            md.update(buff);
            buff.clear();
        }
        byte[] hashValue = md.digest();
        return new String(hashValue);
    }
    catch (NoSuchAlgorithmException e)
    {
        return null;
    } 
    catch (IOException e) 
    {
        return null;
    }
    finally
    {
        try {
            if(inputStream!=null)inputStream.close();
        } catch (IOException e) {

        }
    } 
}

Na moim komputerze wygenerowanie kodu md5 dla dużego pliku zajmuje około 30s, oczywiście testuję również Twój kod, wynik wskazuje, że nio nie poprawia wydajności programu.

Następnie staram się uzyskać czas dla io i md5 odpowiednio, statystyki wskazują, że powolny plik io jest wąskim gardłem, ponieważ około 5/6 czasu jest brane dla io.

Używając szybkiej biblioteki MD5 wspomniany przez @Sticky, potrzeba tylko 15s, aby wygenerować Kod md5, poprawa jest niezwykła.

 12
Author: Alanmars,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-17 03:12:17

Gdy prędkość jest problemem i pobierasz plik z adresu URL i chcesz obliczyć jego MD5 w tym samym czasie( tzn. nie zapisać pliku, otworzyć ponownie i przeczytać ponownie tylko po to, aby uzyskać jego MD5), moje rozwiązanie na https://stackoverflow.com/a/11189634/1082681 może być pomocne. Jest on oparty na fragmencie kodu Bloodwulfa tutaj w tym wątku (dzięki!) i tylko trochę ją wydłuża.

 0
Author: kriegaex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:16