【轉】Java計算文件的hash值

原文地址:http://blog.csdn.net/qq_25646191/article/details/78863110java

如何知道一個文件是否改變了呢?固然是用比較文件hash值的方法,文件hash又叫文件簽名,文件中哪怕一個bit位被改變了,文件hash就會不一樣。

比較經常使用的文件hash算法有MD5和SHA-1。
我用的是MD5算法,java中,計算MD5能夠用MessageDigest這個類。算法

下面是代碼:windows

 

[java]  view plain copy
  1. package com.test;    
  2.     
  3. import java.io.FileInputStream;    
  4. import java.io.FileNotFoundException;    
  5. import java.io.InputStream;    
  6. import java.math.BigInteger;    
  7. import java.security.MessageDigest;    
  8.     
  9. public class MD5Util {    
  10.         
  11.     public static void main(String[] args) {    
  12.         try {    
  13.             //此處我測試的是我本機jdk源碼文件的MD5值   
  14.             String filePath = "C:\\Program Files\\Java\\jdk1.7.0_45\\src.zip";  
  15.               
  16.             String md5Hashcode = md5HashCode(filePath);  
  17.             String md5Hashcode32 = md5HashCode32(filePath);    
  18.               
  19.             System.out.println(md5Hashcode + ":文件的md5值");    
  20.             System.out.println(md5Hashcode32+":文件32位的md5值");   
  21.               
  22.             //System.out.println(-100 & 0xff);  
  23.         } catch (FileNotFoundException e) {    
  24.             e.printStackTrace();    
  25.         }    
  26.     }    
  27.       
  28.     /** 
  29.      * 獲取文件的md5值 ,有可能不是32位 
  30.      * @param filePath  文件路徑 
  31.      * @return 
  32.      * @throws FileNotFoundException 
  33.      */  
  34.     public static String md5HashCode(String filePath) throws FileNotFoundException{    
  35.         FileInputStream fis = new FileInputStream(filePath);    
  36.         return md5HashCode(fis);    
  37.     }    
  38.       
  39.     /** 
  40.      * 保證文件的MD5值爲32位 
  41.      * @param filePath  文件路徑 
  42.      * @return 
  43.      * @throws FileNotFoundException 
  44.      */  
  45.     public static String md5HashCode32(String filePath) throws FileNotFoundException{    
  46.         FileInputStream fis = new FileInputStream(filePath);    
  47.         return md5HashCode32(fis);    
  48.     }    
  49.       
  50.     /** 
  51.      * java獲取文件的md5值   
  52.      * @param fis 輸入流 
  53.      * @return 
  54.      */  
  55.     public static String md5HashCode(InputStream fis) {    
  56.         try {    
  57.             //拿到一個MD5轉換器,若是想使用SHA-1或SHA-256,則傳入SHA-1,SHA-256    
  58.             MessageDigest md = MessageDigest.getInstance("MD5");   
  59.               
  60.             //分屢次將一個文件讀入,對於大型文件而言,比較推薦這種方式,佔用內存比較少。  
  61.             byte[] buffer = new byte[1024];    
  62.             int length = -1;    
  63.             while ((length = fis.read(buffer, 0, 1024)) != -1) {    
  64.                 md.update(buffer, 0, length);    
  65.             }    
  66.             fis.close();  
  67.             //轉換並返回包含16個元素字節數組,返回數值範圍爲-128到127  
  68.             byte[] md5Bytes  = md.digest();  
  69.             BigInteger bigInt = new BigInteger(1, md5Bytes);//1表明絕對值   
  70.             return bigInt.toString(16);//轉換爲16進制  
  71.         } catch (Exception e) {    
  72.             e.printStackTrace();    
  73.             return "";    
  74.         }    
  75.     }    
  76.       
  77.     /** 
  78.      * java計算文件32位md5值 
  79.      * @param fis 輸入流 
  80.      * @return 
  81.      */  
  82.     public static String md5HashCode32(InputStream fis) {  
  83.         try {  
  84.             //拿到一個MD5轉換器,若是想使用SHA-1或SHA-256,則傳入SHA-1,SHA-256    
  85.             MessageDigest md = MessageDigest.getInstance("MD5");  
  86.               
  87.             //分屢次將一個文件讀入,對於大型文件而言,比較推薦這種方式,佔用內存比較少。  
  88.             byte[] buffer = new byte[1024];  
  89.             int length = -1;  
  90.             while ((length = fis.read(buffer, 0, 1024)) != -1) {  
  91.                 md.update(buffer, 0, length);  
  92.             }  
  93.             fis.close();  
  94.               
  95.             //轉換並返回包含16個元素字節數組,返回數值範圍爲-128到127  
  96.             byte[] md5Bytes  = md.digest();  
  97.             StringBuffer hexValue = new StringBuffer();  
  98.             for (int i = 0; i < md5Bytes.length; i++) {  
  99.                 int val = ((int) md5Bytes[i]) & 0xff;//解釋參見最下方  
  100.                 if (val < 16) {  
  101.                     /** 
  102.                      * 若是小於16,那麼val值的16進制形式必然爲一位, 
  103.                      * 由於十進制0,1...9,10,11,12,13,14,15 對應的 16進製爲 0,1...9,a,b,c,d,e,f; 
  104.                      * 此處高位補0。 
  105.                      */  
  106.                     hexValue.append("0");  
  107.                 }  
  108.                 //這裏藉助了Integer類的方法實現16進制的轉換   
  109.                 hexValue.append(Integer.toHexString(val));  
  110.             }  
  111.             return hexValue.toString();  
  112.         } catch (Exception e) {  
  113.             e.printStackTrace();  
  114.             return "";  
  115.         }  
  116.     }  
  117.       
  118.     /** 
  119.      * 方法md5HashCode32 中     ((int) md5Bytes[i]) & 0xff   操做的解釋: 
  120.      * 在Java語言中涉及到字節byte數組數據的一些操做時,常常看到 byte[i] & 0xff這樣的操做,這裏就記錄總結一下這裏包含的意義:  
  121.      * 一、0xff是16進制(十進制是255),它默認爲整形,二進制位爲32位,最低八位是「1111 1111」,其他24位都是0。  
  122.      * 二、&運算: 若是2個bit都是1,則得1,不然得0;  
  123.      * 三、byte[i] & 0xff:首先,這個操做通常都是在將byte數據轉成int或者其餘整形數據的過程當中;使用了這個操做,最終的整形數據只有低8位有數據,其餘位數都爲0。  
  124.      * 四、這個操做得出的整形數據都是大於等於0而且小於等於255的 
  125.      */  
  126.     
  127. }    

 

運行結果以下圖:數組

PS:其實還有一個重點,就是如何知道本身生成的MD5值是否正確呢?app

方法不少,其實有一個挺簡單的方法,不須要另外安裝什麼軟件。測試

使用windows自帶的命令便可:certutil -hashfile [文件路徑] MD5,spa

例子以下:.net

相關文章
相關標籤/搜索