2012-02-17 173 views
7

我正在使用Java为某些文件生成MD5哈希。我需要为几个文件生成一个MD5,总大小约为1 GB。 这里是我的代码:使用Java为使用Java的大文件生成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 2012-02-17 02:42:49

+1

无缓冲的IO缓慢,11时消息。 – 2012-04-16 16:55:56

回答

18

您可能需要使用Fast MD5库。它比Java的内置MD5提供更快和获得哈希很简单,只要:

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

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

11

我重写使用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) { 

     } 
    } 
} 

在我的机器,它需要大约30秒生成MD5码为一个大文件,当然我测试你的代码好,结果表明nio并没有提高程序的性能。

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

通过使用@Sticky提到的Fast MD5库,生成md5代码只需要15s,改进非常显着。

0

每当速度是一个问题,你从一个URL下载文件想在同一时间来计算其MD5(即不保存文件,重新再读只是为了得到它的MD5),我的解决方案在https://stackoverflow.com/a/11189634/1082681可能会有帮助。它基于此线程中的Bloodwulf的代码片段(谢谢!),并将其扩展一点。