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

10

我正在使用Java为一些文件生成MD5哈希值。我需要为总大小约为1GB的几个文件生成一个MD5。

这是我的代码:

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

这个代码似乎会一直运行下去。 我该如何让它更有效率?


1
哎呀,finally 块中的 inputStream 不可能是 null - BalusC
1
非缓冲的I/O速度很慢,这并不是新闻。 - Bruno Rohée
3个回答

20
你可能希望使用Fast MD5库。它比Java内置的MD5提供程序更快,获取哈希值就像这样简单:
String hash = MD5.asHex(MD5.getHash(new File(filename)));

请注意,慢速度也可能是由于缓慢的文件输入/输出所致。


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提到的快速MD5库,只需要15秒即可生成MD5代码,改进非常明显。


0

每当速度成为问题,您从URL下载文件并且同时想要计算其MD5(即不保存文件,重新打开和再次读取以获取其MD5)时,我的解决方案https://dev59.com/73RC5IYBdhLWcg3wFM_X#11189634可能会有所帮助。它基于Bloodwulf在此线程中的代码片段(感谢!)并稍作扩展。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接