標籤:comm stringbu ref static data 轉換 .net md5值 return
原文地址:http://blog.csdn.net/qq_25646191/article/details/78863110
如何知道一個檔案是否改變了呢?當然是用比較檔案hash值的方法,檔案hash又叫檔案簽名,檔案中哪怕一個bit位被改變了,檔案hash就會不同。
比較常用的檔案hash演算法有MD5和SHA-1。
我用的是MD5演算法,java中,計算MD5可以用MessageDigest這個類。
下面是代碼:
[java] view plain copy
- package com.test;
-
- import java.io.FileInputStream;
- import java.io.FileNotFoundException;
- import java.io.InputStream;
- import java.math.BigInteger;
- import java.security.MessageDigest;
-
- public class MD5Util {
-
- public static void main(String[] args) {
- try {
- //此處我測試的是我本機jdk源碼檔案的MD5值
- String filePath = "C:\\Program Files\\Java\\jdk1.7.0_45\\src.zip";
-
- String md5Hashcode = md5HashCode(filePath);
- String md5Hashcode32 = md5HashCode32(filePath);
-
- System.out.println(md5Hashcode + ":檔案的md5值");
- System.out.println(md5Hashcode32+":檔案32位的md5值");
-
- //System.out.println(-100 & 0xff);
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- }
- }
-
- /**
- * 擷取檔案的md5值 ,有可能不是32位
- * @param filePath 檔案路徑
- * @return
- * @throws FileNotFoundException
- */
- public static String md5HashCode(String filePath) throws FileNotFoundException{
- FileInputStream fis = new FileInputStream(filePath);
- return md5HashCode(fis);
- }
-
- /**
- * 保證檔案的MD5值為32位
- * @param filePath 檔案路徑
- * @return
- * @throws FileNotFoundException
- */
- public static String md5HashCode32(String filePath) throws FileNotFoundException{
- FileInputStream fis = new FileInputStream(filePath);
- return md5HashCode32(fis);
- }
-
- /**
- * java擷取檔案的md5值
- * @param fis 輸入資料流
- * @return
- */
- public static String md5HashCode(InputStream fis) {
- try {
- //拿到一個MD5轉換器,如果想使用SHA-1或SHA-256,則傳入SHA-1,SHA-256
- MessageDigest md = MessageDigest.getInstance("MD5");
-
- //分多次將一個檔案讀入,對於大型檔案而言,比較推薦這種方式,佔用記憶體比較少。
- byte[] buffer = new byte[1024];
- int length = -1;
- while ((length = fis.read(buffer, 0, 1024)) != -1) {
- md.update(buffer, 0, length);
- }
- fis.close();
- //轉換並返回包含16個元素位元組數組,返回數值範圍為-128到127
- byte[] md5Bytes = md.digest();
- BigInteger bigInt = new BigInteger(1, md5Bytes);//1代表絕對值
- return bigInt.toString(16);//轉換為16進位
- } catch (Exception e) {
- e.printStackTrace();
- return "";
- }
- }
-
- /**
- * java計算檔案32位md5值
- * @param fis 輸入資料流
- * @return
- */
- public static String md5HashCode32(InputStream fis) {
- try {
- //拿到一個MD5轉換器,如果想使用SHA-1或SHA-256,則傳入SHA-1,SHA-256
- MessageDigest md = MessageDigest.getInstance("MD5");
-
- //分多次將一個檔案讀入,對於大型檔案而言,比較推薦這種方式,佔用記憶體比較少。
- byte[] buffer = new byte[1024];
- int length = -1;
- while ((length = fis.read(buffer, 0, 1024)) != -1) {
- md.update(buffer, 0, length);
- }
- fis.close();
-
- //轉換並返回包含16個元素位元組數組,返回數值範圍為-128到127
- byte[] md5Bytes = md.digest();
- StringBuffer hexValue = new StringBuffer();
- for (int i = 0; i < md5Bytes.length; i++) {
- int val = ((int) md5Bytes[i]) & 0xff;//解釋參見最下方
- if (val < 16) {
- /**
- * 如果小於16,那麼val值的16進位形式必然為一位,
- * 因為十進位0,1...9,10,11,12,13,14,15 對應的 16進位為 0,1...9,a,b,c,d,e,f;
- * 此處高位補0。
- */
- hexValue.append("0");
- }
- //這裡藉助了Integer類的方法實現16進位的轉換
- hexValue.append(Integer.toHexString(val));
- }
- return hexValue.toString();
- } catch (Exception e) {
- e.printStackTrace();
- return "";
- }
- }
-
- /**
- * 方法md5HashCode32 中 ((int) md5Bytes[i]) & 0xff 操作的解釋:
- * 在Java語言中涉及到位元組byte數組資料的一些操作時,經常看到 byte[i] & 0xff這樣的操作,這裡就記錄總結一下這裡包含的意義:
- * 1、0xff是16進位(十進位是255),它預設為整形,二進位位為32位,最低八位是“1111 1111”,其餘24位都是0。
- * 2、&運算: 如果2個bit都是1,則得1,否則得0;
- * 3、byte[i] & 0xff:首先,這個操作一般都是在將byte資料轉成int或者其他整形資料的過程中;使用了這個操作,最終的整形資料只有低8位有資料,其他位元都為0。
- * 4、這個操作得出的整形資料都是大於等於0並且小於等於255的
- */
-
- }
運行結果如:
PS:其實還有一個重點,就是如何知道自己產生的MD5值是否正確呢?
方法很多,其實有一個挺簡單的方法,不需要另外安裝什麼軟體。
使用windows內建的命令即可:certutil -hashfile [檔案路徑] MD5,
例子如下:
【轉】Java計算檔案的hash值