生成文件md5校验码可满足大于2G情况
对于文件生成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情况相关推荐
- java 文件md5校验_Java 获取 文件md5校验码
讯雷下载的核心思想是校验文件的md5值,两个文件若md5相同则为同一文件. 当得到用户下载某个文件的请求后它根据数据库中保留的文件md5比对出拥有此文件的url, 将用户请求挂接到此url上并仿造一个 ...
- Linux查看文件MD5校验码命令,讲解Linux中校验文件的MD5码与SHA1码的命令使用
md5sum 用法:md5sum [选项]... [文件]... 显示或检查 MD5(128-bit) 校验和. 若没有文件选项,或者文件处为"-",则从标准输入读取. -b, - ...
- md5校验 java_java生成MD5校验码
在Java中,java.security.MessageDigest (rt.jar中)已经定义了 MD5 的计算,所以我们只需要简单地调用即可得到 MD5 的128 位整数.然后将此 128 位计 ...
- android MD5校验码的生成与算法实现
android MD5校验码的生成与算法实现 在Java中,java.security.MessageDigest (rt.jar中)已经定义了 MD5 的计算,所以我们只需要简单地调用即可得到 MD ...
- 脚本_根据 md5 校验码,检测文件是否被修改
#!bin/bash #功能:根据 md5 校验码,检测文件是否被修改 #作者:liusingbon #本示例脚本检测的是/etc 目录下所有的 conf 结尾的文件,根据实际情况,您可以修改为其他目 ...
- 如何查看文件的md5校验码、sha1校验码和sha256校验码
如何查看文件的md5校验码.sha1校验码和sha256校验码 本文是基于Windows 10系统和ubuntu 14.04系统环境,使用命令查看文件的md5校验码.sha1校验码和sha256校验码 ...
- 根据 md5 校验码,检测文件是否被修改
根据 md5 校验码,检测文件是否被修改 #!/bin/bash #本示例脚本检测的是/etc 目录下所有的 conf 结尾的文件,根据实际情况,您可以修改为其他目录或文件 #本脚本在目标数据没有被修 ...
- 文件完整性校验码计算工具
文件完整性校验码计算工具 工具介绍 支持算法:CRC32,MD2,MD4,MD5,SHA1,SHA256,SHA512,RipeMD128,RIPEMD160,ED2K 多个哈希类型可以同时生成每个文 ...
- 红帽子redhat linux 9.0官方下载地址,附MD5校验码
红帽子redhat linux 9.0官方下载地址如下: https://archive.download.redhat.com/pub/redhat/linux/9/en/iso/i386/shri ...
最新文章
- 百度编辑器修改,不让它自动替换html标签
- android通知栏打开actvity,Android实现点击通知栏后,先启动应用再打开目标Activity...
- python语言格式化输出_Python format()格式化输出方法详解
- 从“共享马扎”的营销,看共享经济的刷屏玩法
- LiberOJ #6210. 「美团 CodeM 决赛」tree 树形DP
- shell 取中间行的第一列_shell脚本的使用该熟练起来了,你说呢?(篇三)
- 分布式实时计算—Storm—基础介绍
- 将.NET dll注册到GAC(Global Assembly Cache)中
- 忍着疼痛奔跑,带着泪光微笑!
- 《人生一串》第二季收官 B站播放量突破5400万
- LINUX SHELL删除文件中的回车(WINDOWS转LINUX)
- [导入]Manning.Ajax.in.Action.Oct.2005.pdf(9.26 MB)
- 如何区分abcd类地址_ip地址abc类怎么区分
- linux qt程序向windows移植失败记.
- 【chp3】代码调试-车万翔-自然语言处理:基于预训练模型的方法
- 利用快速傅里叶计算多项式相乘
- 【2021最新综述】Deep Neural Approaches to Relation Triplets Extraction:A Comprehensive Survey
- 《计算机是怎样跑起来的》学习笔记
- C++——求平均数、求和函数
- 过宝塔php大马,分享宝塔网站防火墙使用帮助
热门文章
- 基于表单的暴力破解演示
- 大唐卫星网络电视 终身版 下载
- 什么是 XML?什么是HTML?什么是XHTML? XML、HTML和XHTM的区别及联系
- python绘制概率密度曲线_python添加概率密度曲线-女性时尚流行美容健康娱乐mv-ida网...
- 【设计模式六大原则】:单一职责原则-带你走梦幻西游(一)
- 基于用户投票的排名算法
- XmlDocument操作XML
- 如何抠图换背景?介绍两个抠图换背景的方法
- html首行下沉效果,css仿word首字下沉效果示例
- java开发经验分享