JAVA中獲取文件MD5值的四種方法其實都很類似,因為核心都是通過JAVA自帶的MessageDigest類來實現。獲取文件MD5值主要分為三個步驟,第一步獲取文件的byte信息,第二步通過MessageDigest類進行MD5加密,第三步轉換成16進制的MD5碼值。幾種方法的不同點主要在第一步和第三步上。具體可以看下面的例子:
方法一、
1 private final static String[] strHex = { "0", "1", "2", "3", "4", "5", 2 "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" }; 3 4 public static String getMD5One(String path) { 5 StringBuffer sb = new StringBuffer(); 6 try { 7 MessageDigest md = MessageDigest.getInstance("MD5"); 8 byte[] b = md.digest(FileUtils.readFileToByteArray(new File(path))); 9 for (int i = 0; i < b.length; i++) { 10 int d = b[i]; 11 if (d < 0) { 12 d += 256; 13 } 14 int d1 = d / 16; 15 int d2 = d % 16; 16 sb.append(strHex[d1] + strHex[d2]); 17 } 18 } catch (NoSuchAlgorithmException e) { 19 e.printStackTrace(); 20 } catch (IOException e) { 21 e.printStackTrace(); 22 } 23 return sb.toString(); 24 }
方法一是比較原始的一種實現方法,首先將文件一次性讀入內存,然后通過MessageDigest進行MD5加密,最后再手動將其轉換為16進制的MD5值。
方法二、
1 public static String getMD5Two(String path) { 2 StringBuffer sb = new StringBuffer(""); 3 try { 4 MessageDigest md = MessageDigest.getInstance("MD5"); 5 md.update(FileUtils.readFileToByteArray(new File(path))); 6 byte b[] = md.digest(); 7 int d; 8 for (int i = 0; i < b.length; i++) { 9 d = b[i]; 10 if (d < 0) { 11 d = b[i] & 0xff; 12 // 與上一行效果等同 13 // i += 256; 14 } 15 if (d < 16) 16 sb.append("0"); 17 sb.append(Integer.toHexString(d)); 18 } 19 } catch (NoSuchAlgorithmException e) { 20 e.printStackTrace(); 21 } catch (IOException e) { 22 e.printStackTrace(); 23 } 24 return sb.toString(); 25 }
方法二與方法一不同的地方主要是在步驟三,這里借助了Integer類的方法實現16進制的轉換,比方法一更簡潔一些。PS:JAVA中byte是有負數的,代碼中&0xff的操作與計算機中數據存儲的原理有關,即負數存儲的是二進制的補碼,有興趣的童鞋可以挖一下,這里不展開說。
方法三、
1 public static String getMD5Three(String path) { 2 BigInteger bi = null; 3 try { 4 byte[] buffer = new byte[8192]; 5 int len = 0; 6 MessageDigest md = MessageDigest.getInstance("MD5"); 7 File f = new File(path); 8 FileInputStream fis = new FileInputStream(f); 9 while ((len = fis.read(buffer)) != -1) { 10 md.update(buffer, 0, len); 11 } 12 fis.close(); 13 byte[] b = md.digest(); 14 bi = new BigInteger(1, b); 15 } catch (NoSuchAlgorithmException e) { 16 e.printStackTrace(); 17 } catch (IOException e) { 18 e.printStackTrace(); 19 } 20 return bi.toString(16); 21 }
方法三與前面兩個方法相比,在讀入文件信息上有點不同。這里是分多次將一個文件讀入,對於大型文件而言,比較推薦這種方式,占用內存比較少。步驟三則是通過BigInteger類提供的方法進行16進制的轉換,與方法二類似。
方法四、
1 DigestUtils.md5Hex(new FileInputStream(path));
方法四應該是最便捷的吧,哈哈,好東西要留在最后,如果你只需要使用標准的MD5,其實一行代碼就夠了,JAVA自帶的commons-codec包就提供了獲取16進制MD5值的方法。其底層實現上,也是分多次將一個文件讀入,類似方法三。所以性能上也不錯。
總結:其實方法都是類似的,推薦使用方法四,簡潔且性能不錯,當然,如果要做一些調整什么的,可以根據自己的需求進行方法的選擇。
PS:其實還有一個重點,就是如何知道自己生成的MD5值是否正確呢?
方法很多,其實有一個挺簡單的方法,不需要另外安裝什么軟件。使用windows自帶的命令即可:certutil -hashfile [文件路徑] MD5,例子如下: