对于文件生成md5校验码,在实际开发中用处很大,有利于比较服务器上是否已经存在该文件,哪怕文件名不一致也无所谓。

由于存在超大文件,经过从网上查找,得到两种方法,一种是利用MappedByteBuffer对于超大文件缓冲,效率高

代码片段如下:

    public static String getFileMD5String_old(File file) throws IOException {  FileInputStream in = new FileInputStream(file);  FileChannel ch = in.getChannel();  MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, 0,  file.length());  messagedigest.update(byteBuffer);  return bufferToHex(messagedigest.digest());  }  
   网上说: /***
          * MappedByteBuffer是NIO的API,使用这个API会有一个bug,
          * 当使用 FileChannel.map 方法时,MappedByteBuffer 已经在系统内占用了一个句柄,
          * 而使用 FileChannel.close 方法是无法释放这个句柄的,、
          * 且FileChannel有没有提供类似 unmap 的方法,因此会出现无法删除文件的情况。
          */

但是我个人觉得,在这里只是将文件流读了一下,这里使用 MappedByteBuffer是安全的,它不适合用在拷贝写操作,不能说是bug,适用场景不同罢了。不知道我的理解对不对。该方法经过测试效率还是很高的,接近2G的文件,本机测试5s就完成了md5校验码生成。遗憾的是该种方法只能生成2G以下文件的校验码,原因在于jdk api中限制了2G( Integer.MAX_VALUE)。

所以查询到如下代码:

       public static String getFileMD52(File file) {if (!file.isFile()){return null;}MessageDigest digest = null;FileInputStream in=null;byte buffer[] = new byte[1024];int len;try {digest = MessageDigest.getInstance("MD5");in = new FileInputStream(file);while ((len = in.read(buffer, 0, 1024)) != -1) {digest.update(buffer, 0, len);}in.close();} catch (Exception e) {e.printStackTrace();return null;}BigInteger bigInt = new BigInteger(1, digest.digest());return bigInt.toString(16);}

该方法适用于所有文件读写,经测试了一个超过2G小于3G的大文件,生成校验码值本机在15s左右。网上有人对该方法深恶痛绝,说达到950多s,我想是因为他的机器性能太差的缘故吧。我对文件块读写改造后,同样的文件生成速度可以降低到9s,不过在小于2G的文件读写上,性能不如上面的代码,本机测试,大概差了2s-4s。所以我个人经过整合,出现如下代码小于2g, 利用第一个的性能,大于2G利用后者的代码如下,如果保守可以只用>2g的操作:

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class MD5FileUtil {  private static final Logger logger = LoggerFactory  .getLogger(MD5FileUtil.class);  /*** 默认的密码字符串组合,用来将字节转换成 16 进制表示的字符,apache校* 验下载的文件的正确性用的就是默认的这个组合*/protected static char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6',  '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };  protected static MessageDigest messagedigest = null;  static {  try {  messagedigest = MessageDigest.getInstance("MD5");  } catch (NoSuchAlgorithmException e) {  logger.error("MD5FileUtil messagedigest初始化失败", e);  }  }  /*** 生成文件的md5校验值* @param file 文件路径* @return MD5码返回* @throws IOException*/public static String getFileMD5(File file) throws IOException {String encrStr="";// 读取文件FileInputStream fis = new FileInputStream(file);// 当文件<2G可以直接读取if(file.length() <= Integer.MAX_VALUE) {encrStr = getMD5Lt2G(file, fis);} else { // 当文件>2G需要切割读取encrStr = getMD5Gt2G(fis);}fis.close();return encrStr; }/*** 小于2G文件* @param fis 文件输入流* @return* @throws IOException*/public static String getMD5Lt2G(File file, FileInputStream fis) throws IOException {// 加密码String encrStr="";FileChannel ch = fis.getChannel();  MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, 0, file.length());  messagedigest.update(byteBuffer); encrStr = bufferToHex(messagedigest.digest());   return encrStr; }  /*** 超过2G文件的md5算法* @param fileName* @param InputStream* @return* @throws Exception*/public static String getMD5Gt2G(InputStream fis)  throws IOException {   // 自定义文件块读写大小,一般为4M,对于小文件多的情况可以降低byte[] buffer = new byte[1024*1024*4];    int numRead = 0;    while ((numRead = fis.read(buffer)) > 0) {    messagedigest.update(buffer, 0, numRead);    }    return bufferToHex(messagedigest.digest());    }    /*** * @param bt 文件字节流* @param stringbuffer 文件缓存*/private static void appendHexPair(byte bt, StringBuffer stringbuffer) {  // 取字节中高 4 位的数字转换, >>> 为逻辑右移,将符号位一起右移,此处未发现两种符号有何不同char c0 = hexDigits[(bt & 0xf0) >> 4]; // 取字节中低 4 位的数字转换char c1 = hexDigits[bt & 0xf];  stringbuffer.append(c0);  stringbuffer.append(c1);  }  private static String bufferToHex(byte bytes[], int m, int n) {  StringBuffer stringbuffer = new StringBuffer(2 * n);  int k = m + n;  for (int l = m; l < k; l++) {  appendHexPair(bytes[l], stringbuffer);  }  return stringbuffer.toString();  }  private static String bufferToHex(byte bytes[]) {  return bufferToHex(bytes, 0, bytes.length);  }  /*** 判断字符串的md5校验码是否与一个已知的md5码相匹配* * @param password 要校验的字符串* @param md5PwdStr 已知的md5校验码* @return*/public static boolean checkPassword(String password, String md5PwdStr) {  String s = getMD5String(password);  return s.equals(md5PwdStr);  }  /*** 生成字符串的md5校验值* * @param s* @return*/public static String getMD5String(String s) {  return getMD5String(s.getBytes());  }  /*** 生成字节流的md5校验值* * @param s* @return*/public static String getMD5String(byte[] bytes) {  messagedigest.update(bytes);  return bufferToHex(messagedigest.digest());  }  public static void main(String[] args) throws IOException {  long begin = System.currentTimeMillis();  File big = new File("F:/迅雷下载/港囧.TC1280清晰国语中字.mp4");  String md5 = getFileMD5(big);  long end = System.currentTimeMillis();  System.out.println("md5:" + md5);  System.out.println("time:" + ((end - begin) / 1000) + "s");  }  }  

生成文件md5校验码可满足大于2G情况相关推荐

  1. java 文件md5校验_Java 获取 文件md5校验码

    讯雷下载的核心思想是校验文件的md5值,两个文件若md5相同则为同一文件. 当得到用户下载某个文件的请求后它根据数据库中保留的文件md5比对出拥有此文件的url, 将用户请求挂接到此url上并仿造一个 ...

  2. Linux查看文件MD5校验码命令,讲解Linux中校验文件的MD5码与SHA1码的命令使用

    md5sum 用法:md5sum [选项]... [文件]... 显示或检查 MD5(128-bit) 校验和. 若没有文件选项,或者文件处为"-",则从标准输入读取. -b, - ...

  3. md5校验 java_java生成MD5校验码

    在Java中,java.security.MessageDigest (rt.jar中)已经定义了 MD5 的计算,所以我们只需要简单地调用即可得到 MD5 的128 位整数.然后将此 128 位计 ...

  4. android MD5校验码的生成与算法实现

    android MD5校验码的生成与算法实现 在Java中,java.security.MessageDigest (rt.jar中)已经定义了 MD5 的计算,所以我们只需要简单地调用即可得到 MD ...

  5. 脚本_根据 md5 校验码,检测文件是否被修改

    #!bin/bash #功能:根据 md5 校验码,检测文件是否被修改 #作者:liusingbon #本示例脚本检测的是/etc 目录下所有的 conf 结尾的文件,根据实际情况,您可以修改为其他目 ...

  6. 如何查看文件的md5校验码、sha1校验码和sha256校验码

    如何查看文件的md5校验码.sha1校验码和sha256校验码 本文是基于Windows 10系统和ubuntu 14.04系统环境,使用命令查看文件的md5校验码.sha1校验码和sha256校验码 ...

  7. 根据 md5 校验码,检测文件是否被修改

    根据 md5 校验码,检测文件是否被修改 #!/bin/bash #本示例脚本检测的是/etc 目录下所有的 conf 结尾的文件,根据实际情况,您可以修改为其他目录或文件 #本脚本在目标数据没有被修 ...

  8. 文件完整性校验码计算工具

    文件完整性校验码计算工具 工具介绍 支持算法:CRC32,MD2,MD4,MD5,SHA1,SHA256,SHA512,RipeMD128,RIPEMD160,ED2K 多个哈希类型可以同时生成每个文 ...

  9. 红帽子redhat linux 9.0官方下载地址,附MD5校验码

    红帽子redhat linux 9.0官方下载地址如下: https://archive.download.redhat.com/pub/redhat/linux/9/en/iso/i386/shri ...

最新文章

  1. 百度编辑器修改,不让它自动替换html标签
  2. android通知栏打开actvity,Android实现点击通知栏后,先启动应用再打开目标Activity...
  3. python语言格式化输出_Python format()格式化输出方法详解
  4. 从“共享马扎”的营销,看共享经济的刷屏玩法
  5. LiberOJ #6210. 「美团 CodeM 决赛」tree 树形DP
  6. shell 取中间行的第一列_shell脚本的使用该熟练起来了,你说呢?(篇三)
  7. 分布式实时计算—Storm—基础介绍
  8. 将.NET dll注册到GAC(Global Assembly Cache)中
  9. 忍着疼痛奔跑,带着泪光微笑!
  10. 《人生一串》第二季收官 B站播放量突破5400万
  11. LINUX SHELL删除文件中的回车(WINDOWS转LINUX)
  12. [导入]Manning.Ajax.in.Action.Oct.2005.pdf(9.26 MB)
  13. 如何区分abcd类地址_ip地址abc类怎么区分
  14. linux qt程序向windows移植失败记.
  15. 【chp3】代码调试-车万翔-自然语言处理:基于预训练模型的方法
  16. 利用快速傅里叶计算多项式相乘
  17. 【2021最新综述】Deep Neural Approaches to Relation Triplets Extraction:A Comprehensive Survey
  18. 《计算机是怎样跑起来的》学习笔记
  19. C++——求平均数、求和函数
  20. 过宝塔php大马,分享宝塔网站防火墙使用帮助

热门文章

  1. 基于表单的暴力破解演示
  2. 大唐卫星网络电视 终身版 下载
  3. 什么是 XML?什么是HTML?什么是XHTML? XML、HTML和XHTM的区别及联系
  4. python绘制概率密度曲线_python添加概率密度曲线-女性时尚流行美容健康娱乐mv-ida网...
  5. 【设计模式六大原则】:单一职责原则-带你走梦幻西游(一)
  6. 基于用户投票的排名算法
  7. XmlDocument操作XML
  8. 如何抠图换背景?介绍两个抠图换背景的方法
  9. html首行下沉效果,css仿word首字下沉效果示例
  10. java开发经验分享