一般用來判斷某個檔案是否上傳或下載完整~當然也可以用在檔案複製貼上等等的動作。
之前在做這種需求時,都是直接用 Runtime 呼叫 Linux 的 md5sum
不過總是覺得一直依賴底層 OS 的指令,好像不是個非常完美的作法!
尤其考慮到程式未來可能需要移植到別的平台時,大量使用 Runtime 會導致移植時要花費的功夫暴增。
今天稍微查了一下,原來 Java 原生就有可以計算 MD5/SHA1 hash 的方法!
雖然不清楚 Java 算出來的 hash 值是否跟用其他方式算出來的 hash 值相同,但老實說那並不是很重要 XD
畢竟 MD5 hash 這種東西只要能確認同一個檔案,每次算出來都一樣;不同檔案算出來都不一樣,能達到這個目的就好了!
以下是用 MD5 查詢 hash 值的程式碼,程式碼基本上是參考 [2] 的範例的。
import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.security.DigestInputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Formatter; public class MD5hash { public static String getMD5Hash (File file) throws IOException { if(!file.exists()) throw new IOException("The file is not exist."); FileInputStream fis = null; DigestInputStream dis = null; byte[] buff = new byte[1024]; try { MessageDigest md = MessageDigest.getInstance("MD5"); fis = new FileInputStream(file); dis = new DigestInputStream(fis, md); // Read bytes from the file. while(dis.read(buff) != -1); byte[] md5Digests = md.digest(); return byteArray2Hex(md5Digests); } catch (IOException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } finally { buff = null; if(fis != null) fis.close(); if(dis != null) dis.close(); } return null; } /** * Convert byte array into hex. * @param hash * @return */ public static String byteArray2Hex(byte[] hash) { Formatter formatter = new Formatter(); for (byte b : hash) { formatter.format("%02x", b); } return formatter.toString(); } }
其中 18 行是指定 hash 演算法的地方,如果想要用 SHA1 演算法的話,把 "MD5" 改成 "SHA1" 即可。
2012-10-15 補充
如果在複製檔案時,複製完再重新掃一次檔案算 MD5 hash,感覺是有點浪費時間
因此稍微查了一下,實際上在做 FileInputStream、FileOutputStream 時,是可以直接邊讓他算 hash 的
詳情可以參考 [3] 的範例。
但剛剛測試下來,好像是沒什麼差 XD,也許是我測試的檔案容量(159KB)太小了吧!
參考資料:
1、Getting a File's MD5 Checksum in Java
2、SHA1 and MD5 checksums in Java
3、DigestInputStream --还是与下载有关的
沒有留言:
張貼留言