2012-02-17 24 views
7

Estoy usando Java para generar el hash MD5 para algunos archivos. Necesito generar un MD5 para varios archivos con un tamaño total de aproximadamente 1 gigabyte. Aquí está mi código:Muy lento para generar MD5 para archivos grandes usando Java

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

}

Esto parece funcionar para siempre. ¿Cómo puedo hacerlo más eficiente?

+1

Pssh, el 'inputStream' puede ser imposiblemente' nulo' en el bloque 'finally'. – BalusC

+1

IO sin búfer son lentos, noticias en 11. –

Respuesta

18

Es posible que desee utilizar la biblioteca Fast MD5. Es mucho más rápido que el proveedor de MD5 incorporado en Java y conseguir un hash es tan simple como:

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

Tenga en cuenta que la velocidad lenta también puede ser debido a la lentitud del archivo de E/S.

11

vuelvo a escribir el código con nio, el código es un poco como a continuación:

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

     } 
    } 
} 

En mi máquina, se tarda unos 30 años para generar el código MD5 de un archivo de gran tamaño, y por supuesto que probar el código como bueno, el resultado indica que nio no mejora el rendimiento del programa.

Luego, intento obtener el tiempo para io y md5, respectivamente, las estadísticas indican que el archivo lento io es el cuello de botella porque se toma aproximadamente 5/6 de tiempo para io.

Al utilizar la biblioteca Fast MD5 mencionada por @Sticky, solo se necesitan 15 segundos para generar el código md5, la mejora es notable.

0

Cuando la velocidad sea un problema y descargue un archivo de una URL y desee calcular su MD5 al mismo tiempo (es decir, no guarde el archivo, vuelva a abrirlo y vuelva a leerlo solo para obtener su MD5), mi solución https://stackoverflow.com/a/11189634/1082681 podría ser útil. Se basa en el fragmento de código de Bloodwulf aquí en este hilo (¡gracias!) Y simplemente lo extiende un poco.

Cuestiones relacionadas