如何知道一个文件是否改变了呢?当然是用比较文件hash值的方法,文件hash又叫文件签名,文件中哪怕一个bit位被改变了,文件hash就会不同。

比较常用的文件hash算法有MD5和SHA-1。
我用的是MD5算法,java中,计算MD5可以用MessageDigest这个类。

下面是代码:

 

[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. "C:\\Program Files\\Java\\jdk1.7.0_45\\src.zip";  
15.               
16.             String md5Hashcode = md5HashCode(filePath);  
17.             String md5Hashcode32 = md5HashCode32(filePath);    
18.               
19. ":文件的md5值");    
20. ":文件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. 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. 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. "MD5");   
59.               
60. //分多次将一个文件读入,对于大型文件而言,比较推荐这种方式,占用内存比较少。  
61. byte[] buffer = new byte[1024];    
62. int length = -1;    
63. while ((length = fis.read(buffer, 0, 1024)) != -1) {    
64. 0, length);    
65.             }    
66.             fis.close();  
67. //转换并返回包含16个元素字节数组,返回数值范围为-128到127  
68. byte[] md5Bytes  = md.digest();  
69. 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. "MD5");  
86.               
87. //分多次将一个文件读入,对于大型文件而言,比较推荐这种方式,占用内存比较少。  
88. byte[] buffer = new byte[1024];  
89. int length = -1;  
90. while ((length = fis.read(buffer, 0, 1024)) != -1) {  
91. 0, length);  
92.             }  
93.             fis.close();  
94.               
95. //转换并返回包含16个元素字节数组,返回数值范围为-128到127  
96. byte[] md5Bytes  = md.digest();  
97. 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. "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.      * 1、0xff是16进制(十进制是255),它默认为整形,二进制位为32位,最低八位是“1111 1111”,其余24位都是0。  
122.      * 2、&运算: 如果2个bit都是1,则得1,否则得0;  
123.      * 3、byte[i] & 0xff:首先,这个操作一般都是在将byte数据转成int或者其他整形数据的过程中;使用了这个操作,最终的整形数据只有低8位有数据,其他位数都为0。  
124.      * 4、这个操作得出的整形数据都是大于等于0并且小于等于255的 
125.      */  
126.     
127. }

 

运行结果如下图:

Java输出哈西码值怎么改回去 java计算文件hash码_java

PS:其实还有一个重点,就是如何知道自己生成的MD5值是否正确呢?

方法很多,其实有一个挺简单的方法,不需要另外安装什么软件。

使用windows自带的命令即可:certutil -hashfile [文件路径] MD5,

例子如下:

Java输出哈西码值怎么改回去 java计算文件hash码_java_02