zoukankan      html  css  js  c++  java
  • 【转】Java计算文件的hash值

    原文地址: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
    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.      * 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. }    

    运行结果如下图:

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

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

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

    例子如下:

  • 相关阅读:
    java开发中的重中之重-------mysql(基础篇)
    开发中的重点-----设计模式
    java 不可不知的数据库知识-----事物
    redis 入门笔记
    转 Java对日期Date类进行加减运算一二三
    Ajax 中的高级请求和响应
    Ajax之基础总结
    Spring中的国际化资源以及视图跳转
    javascript基础总结
    SpringMVC的表单标签
  • 原文地址:https://www.cnblogs.com/dirgo/p/8350645.html
Copyright © 2011-2022 走看看