使用Java为大文件生成MD5非常慢

时间:2012-02-17 01:59:00

标签: java performance file md5 checksum

我正在使用Java为某些文件生成MD5哈希。我需要为几个文件生成一个MD5,总大小约为1千兆字节。 这是我的代码:

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) {
            // ...
        }
    } 

}

这似乎永远存在。 我怎样才能提高效率呢?

3 个答案:

答案 0 :(得分:19)

您可能想要使用Fast MD5库。它比Java的内置MD5提供程序快得多,并且获取哈希就像这样简单:

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

请注意,速度慢也可能是由于文件I / O速度慢。

答案 1 :(得分:12)

我用nio重写代码,代码如下:

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) {

        }
    } 
}

在我的机器上,为大文件生成md5代码大约需要30秒,当然我也会测试你的代码,结果表明nio不会提高程序的性能。

然后,我试图分别获得io和md5的时间,统计数据表明慢速文件io是瓶颈,因为大约有5/6的时间用于io。

通过使用@Sticky提到的Fast MD5库,生成md5代码只需15秒,效果显着。

答案 2 :(得分:0)

每当速度出现问题并且您从URL 下载文件并且想要同时计算其MD5时(即不保存文件,重新打开并再次读取以获取其MD5) ,我在https://stackoverflow.com/a/11189634/1082681的解决方案可能会有所帮助。它基于Bloodwulf的代码片段在这个帖子中(谢谢!)并且只是扩展了一点。