Java 內建MD5 校正檔案

來源:互聯網
上載者:User

標籤:

http://www.iteye.com/topic/1127319

 

前天第一次發表部落格到論壇,關於Java檔案監控一文,文章地址在:http://www.iteye.com/topic/1127281

評論的朋友很多,下載代碼的朋友很不少,感謝在論壇上看我文章的朋友,還有回複評論的朋友,給我提供建議的朋友。

 

從這些建議中,雖然語言簡短,但是卻有的是一語中的,這裡說一下一下關於文章的代碼中HashFile中的MD5檔案校正演算法,

該演算法是使用Java內建的MessageDigest類,測試結果,擷取一個2G檔案的MD5碼,耗時 971秒,這效率太給力了,可以用坑爹來形容,所以用MD5檔案校正碼來判斷檔案是否被修改,對於小檔案來說可能還合適,要是對大檔案來說,好吧,撞牆死了算了!

 

HashFile中的代碼是這樣子的:

import java.io.FileInputStream;
import java.io.InputStream;
import java.security.MessageDigest;

public class HashFile { 
 
    /**
     * @param args
     */ 
    public static char[] hexChar = { ‘0‘, ‘1‘, ‘2‘, ‘3‘, ‘4‘, ‘5‘, ‘6‘, ‘7‘, 
            ‘8‘, ‘9‘, ‘a‘, ‘b‘, ‘c‘, ‘d‘, ‘e‘, ‘f‘ };
 
    public static String getHash(String fileName, String hashType) 
            throws Exception { 
        InputStream fis; 
        fis = new FileInputStream(fileName); 
        byte[] buffer = new byte[1024]; 
        MessageDigest md5 = MessageDigest.getInstance(hashType); 
        int numRead = 0; 
        while ((numRead = fis.read(buffer)) > 0) { 
            md5.update(buffer, 0, numRead); 
        } 
        fis.close(); 
        return toHexString(md5.digest()); 
    } 
 
    public static String toHexString(byte[] b) { 
        StringBuilder sb = new StringBuilder(b.length * 2); 
        for (int i = 0; i < b.length; i++) { 
            sb.append(hexChar[(b[i] & 0xf0) >>> 4]); 
            sb.append(hexChar[b[i] & 0x0f]); 
        } 
        return sb.toString(); 
    } 

測試結果:


真給力啊,超過2G,效率變成這樣 !

好吧,內建的MD5演算法,上當了,對於檢查檔案是否更新這個問題來說,現在我使用的解決辦法是File 類的lastModified方法,代碼這樣

private String getHash(String fp){
  File file = new File(fp);
  return String.valueOf(file.lastModified());
 }

 通過比較檔案的最後修改時間來判斷檔案是否更新,對大檔案也輕鬆拿下,

測試結果是這樣:



 當然針對不同問題肯定是有不同的解決辦法

 

分析原來HashFile代碼,擷取MD5校正碼的瓶頸是出現在

Java代碼  
  1. public static String getHash(String fileName, String hashType)     
  2.             throws Exception {     
  3.         InputStream fis;     
  4.         fis = new FileInputStream(fileName);     
  5.         byte[] buffer = new byte[1024];     
  6.         MessageDigest md5 = MessageDigest.getInstance(hashType);     
  7.         int numRead = 0;     
  8.         while ((numRead = fis.read(buffer)) > 0) {  //瓶頸   
  9.             md5.update(buffer, 0, numRead);     
  10.         }     
  11.         fis.close();     
  12.         return toHexString(md5.digest());     
  13.     }    
public static String getHash(String fileName, String hashType)              throws Exception {          InputStream fis;          fis = new FileInputStream(fileName);          byte[] buffer = new byte[1024];          MessageDigest md5 = MessageDigest.getInstance(hashType);          int numRead = 0;          while ((numRead = fis.read(buffer)) > 0) {  //瓶頸            md5.update(buffer, 0, numRead);          }          fis.close();          return toHexString(md5.digest());      }  

 在上面代碼中,while迴圈N次,2G的檔案,迴圈1024 * 1024  * 2 次,不給力!

 

chimer回複

來個nio的簡單版,看你們老是懷疑java慢

C++ MD5工具驗證結果:

File: K:\Games\World of Warcraft\Data\common.MPQ
Size: 2226587191 bytes
Modified: 2008年11月19日 星期三, 12:57:24
MD5: CD9F9C5523F3BA3866B81CCC74ED6476


java運行結果,毫秒
耗時:12672,cd9f9c5523f3ba3866b81ccc74ed6476


核心代碼

String hashType = "MD5";
  FileInputStream fStream = null;
  try {
   MessageDigest md5 = MessageDigest.getInstance(hashType);
   fStream = new FileInputStream(
     //"K:\\Games\\World of Warcraft\\Scan.dll");
     //"K:\\Games\\World of Warcraft\\Data\\patch-3.MPQ");
     "K:\\Games\\World of Warcraft\\Data\\common.MPQ");
   FileChannel fChannel = fStream.getChannel();
   ByteBuffer buffer = ByteBuffer.allocate(8*1024);
   long s = System.currentTimeMillis();
   for ( int count = fChannel.read( buffer ); count !=-1 ; count = fChannel.read( buffer )
    ) {
    buffer.flip();
    md5.update( buffer );
    if( !buffer.hasRemaining() ){
     //System.out.println("count:"+count);
     buffer.clear();
    }
   }
   s = System.currentTimeMillis() - s;
   System.out.println( "耗時:"+s+","+getString( md5.digest() ) );
   
  } catch (NoSuchAlgorithmException e) {
   e.printStackTrace();
  } catch (FileNotFoundException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  }finally{
   try {
    if( fStream!=null )
     fStream.close();
   } catch (IOException e) {
    e.printStackTrace();
   }
  }

Java 內建MD5 校正檔案

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.