使用md5来实现文件去重
可以使用MD5算法来实现文件去重,因为它可以接受任意大小的数据并输出固定长度的哈希值。所以两个不一样的文件一般情况下使用MD5计算出来的hash值是不可能会相等的。
所以一旦两个文件计算出来的hash值相同那么他们的文件就是相同的。
这时文件上传的一个例子,先使用md5算法计算文件的hash值,再检测我们磁盘是否有相同的文件名的文件,如果有那我们就不上传直接返回访问路径,如果没有才上传
@Overridepublic String uploadFile(MultipartFile file, String path) {try {// 获取文件md5值String md5 = FileUtils.getMd5(file.getInputStream());// 获取文件扩展名String extName = FileUtils.getExtName(file.getOriginalFilename());// 重新生成文件名String fileName = md5 + extName;System.out.println("filename "+fileName);// 判断文件是否已存在if (!exists(path + fileName)) {// 不存在则继续上传upload(path, fileName, file.getInputStream());}// 返回文件访问路径return getFileAccessUrl(path + fileName);} catch (Exception e) {e.printStackTrace();throw new BizException("文件上传失败");}}
我这就先看一下MD5得到Hash值的逻辑
public static String getMd5(InputStream inputStream) {try {MessageDigest md5 = MessageDigest.getInstance("md5");byte[] buffer = new byte[8192];int length;while ((length = inputStream.read(buffer)) != -1) {md5.update(buffer, 0, length);}return new String(Hex.encodeHex(md5.digest()));} catch (Exception e) {e.printStackTrace();return null;} finally {try {if (inputStream != null) {inputStream.close();}} catch (IOException e) {e.printStackTrace();}}}
这里使用的是JDK自带的MD5算法,也可以替换成其他库提供的MD5算法。讲一下得到MD5算法摘要的大致逻辑,当然不看 得到MD5算法摘要的的逻辑也是可以的,没有影响
先传入我们要得到的算法名称
MessageDigest.getInstance("md5");
MessageDigest.getInstance又会调用这个方法
GetInstance.Instance instance = GetInstance.getInstance("MessageDigest",MessageDigestSpi.class, algorithm);
这里是先得到所有的算法类提供商,再在提供商列表中查找第一个支持该算法的提供商提供的服务类,如果这个服务类能够提供指定的clazz的实例就直接将这个Instance返回,如果不能就找下一个能提供该算法的提供商看行不行。
我们这里的clazz就是MessageDigestSpi类,该类为MessageDigest类定义服务提供者接口(Service Provider Interface, SPI),该类提供消息摘要算法的功能,如MD5或SHA。消息摘要是安全的单向哈希函数,它接受任意大小的数据并输出固定长度的哈希值。
public static Instance getInstance(String type, Class<?> clazz,String algorithm) throws NoSuchAlgorithmException {// in the almost all cases, the first service will work// avoid taking long path if soProviderList list = Providers.getProviderList();Service firstService = list.getService(type, algorithm);if (firstService == null) {throw new NoSuchAlgorithmException(algorithm + " " + type + " not available");}NoSuchAlgorithmException failure;try {return getInstance(firstService, clazz);} catch (NoSuchAlgorithmException e) {failure = e;}for (Service s : list.getServices(type, algorithm)) {if (s == firstService) {// do not retry initial failed servicecontinue;}try {return getInstance(s, clazz);} catch (NoSuchAlgorithmException e) {failure = e;}}throw failure;}
最后返回我们期望的消息摘要算法MessageDigest。除了有MD5以外还有SHA1等等算法可以选择
MessageDigest的方法:
- getInstance 得到算法摘要
- update 处理这些数据
- digest 转换并返回结果,也是字节数组
在校验文件重复性的时候,我们最后一步就是将MD5校验返回的字节数组编码成16进制的字符数组,然后用这个字符数组转换为字符串作为我们文件的名字,如果以后还有同样的文件被上传了,会对比是否有文件名相同的文件。
因为一个字节需要2个16进制数来表示,所以字符数组的大小是字节数组的大小的2倍
public static String encodeHex(byte[] byteArray) {// 首先初始化一个字符数组,用来存放每个16进制字符char[] hexDigits = {'0','1','2','3','4','5','6','7','8','9', 'A','B','C','D','E','F' };// new一个字符数组,这个就是用来组成结果字符串的(解释一下:一个byte是八位二进制,也就是2位十六进制字符(2的8次方等于16的2次方))char[] resultCharArray =new char[byteArray.length * 2];// 遍历字节数组,通过位运算(位运算效率高),转换成字符放到字符数组中去int index = 0;for (byte b : byteArray) {resultCharArray[index++] = hexDigits[b>>> 4 & 0xf];resultCharArray[index++] = hexDigits[b& 0xf];}// 字符数组组合成字符串返回return new String(resultCharArray);}
对于计算文件的MD5 的Hash值时我们可以像这样使用基础的InputStrem
MessageDigest md5 = MessageDigest.getInstance("md5");byte[] buffer = new byte[8192];int length;while ((length = inputStream.read(buffer)) != -1) {md5.update(buffer, 0, length);}byte[] resultByteArray = MD5.digest();
也可以使用DigestInputStream
MessageDigest messageDigest =MessageDigest.getInstance("MD5");// 使用DigestInputStreamDigestInputStream digestInputStream = new DigestInputStream(inputStream,messageDigest);// read的过程中进行MD5处理,直到读完文件byte[] buffer =new byte[bufferSize];while (digestInputStream.read(buffer) > 0);// 获取最终的MessageDigestmessageDigest= digestInputStream.getMessageDigest();byte[] resultByteArray = messageDigest.digest();
使用md5来实现文件去重相关推荐
- python对文件夹内文件去重
昨天无聊写了一个百度图片爬虫,测试了一下搜索"斗图".一下给我下了3000多个图片,关键是有一半以上重复的.what a fuck program ! 好吧,今天写一个文件去重功能 ...
- python去重txt文本_Python 文件去重(转载)
原博文 2020-02-14 13:20 − Python实现的txt文件去重功能示例 更新时间:2018年07月07日 09:00:36 作者:人饭子 我要评论 这篇文章主要介绍了Python实现的 ...
- php读取文件和读取redis,PHP结合redis实现大文件去重
本篇文章主要内容是用PHP多个进程配合redis的有序集合实现大文件去重,感兴趣的朋友可以学习一下. 1.对一个大文件比如我的文件为 -rw-r--r-- 1 ubuntu ubuntu 9.1G M ...
- php redis 集合返回多条,详解PHP多个进程配合redis的有序集合实现大文件去重
1.对一个大文件比如我的文件为 -rw-r--r-- 1 ubuntu ubuntu 9.1G Mar 1 17:53 2018-12-awk-uniq.txt 2.使用split命令切割成10个小文 ...
- 【数据挖掘】利用md5查找重复文件
[数据挖掘]利用md5查找重复文件 电脑经过长时间的使用,难免会存留许多重复文件.这些重复文件往往四散在各处,其文件名.修改时间等信息都有改动,这对我清理重复文件造成了困扰.尽管重复文件已经有了诸多修 ...
- 根据文件MD5删除重复文件
根据文件MD5删除重复文件,仅保留一份文件: ```shell find . -type f -exec md5sum {} \; | sort -k 1 | awk 'a[$1]++{print $ ...
- 单向散列函数概述并基于MD5算法对文件哈希值实时监测
1.如何验证文件是否被修改过 只生成一个指纹文件,对指纹文件进行验证 当已经存储的文件被修改之后,指纹文件就会跟着变化,即生成一个单向散列函数 任意长度的数据都对应固定长度的散列值–减少匹配开销 散列 ...
- c语言压缩并加密算法,C语言压缩文件和用MD5算法校验文件完整性的实例教程
使用lzma SDK对7z文件简单解压缩有时候我们只需要单纯对lzma算法压缩的7z文件进行解压,有时需要在嵌入式设备上解压,使用p7zip虽然支持多种格式,但是不容易裁剪,使用lzma SDK是首选 ...
- python文件去重软件_Python实现的txt文件去重功能示例
本文实例讲述了Python实现的txt文件去重功能.分享给大家供大家参考,具体如下: # -*- coding:utf-8 -*- #! python2 import shutil a=0 readD ...
最新文章
- 软件测试工程师职业介绍和规划
- 2018-3-6论文-网络评论中非结构化信息的应用于研究------(语义矩离)
- 网络慢是带宽不足?优化网络带宽的5个小窍门
- cisco 恢复出厂设置
- Swoole 自定义项目初始化事件处理的实现
- [考试]20150528
- python re findall 效率_python re模块findall()详解
- xheditor可视化富文本编辑器
- table模板标签,批量多选失效的问题,tr td结构多选框失效相关问题
- STM32F303VCT6(数据表) ARM Cortex M4,微控制器
- 2023北京理工大学计算机考研信息汇总
- python 提取元组中的值_如何从Python元组中提取数据?
- 【机器学习】机器学习在爱奇艺视频分析理解中的实践
- Android 长按APP图标弹出快捷方式(shortcuts)
- 水仙花数的判断(JAVA)
- 深入学习Gremlin(5):查询路径path
- 当代最值得收藏的画家作品_名人名画推荐,值得收藏的当代画家作品
- 奥格斯堡水利系统被列入教科文组织世界遗产名录
- 常见几种开关电源工作原理及电路图
- css的div,span,img,a,map等一些常见标签使用 回顶设置
热门文章
- 读取扭力计的COM口数据
- FreeBSD使用总结
- 根据WADL生成REST风格WebService的客户端代码
- elementUI el-table设置fixed后,竖向滚动条滚动到底部表格错位的问题(修改源码)
- cadence自动生成铺铜_Cadence Allegro简易手册连载7:内层及铺铜
- vs2019 自定义工具错误: 未能生成文件: 系统找不到指定的文件。 (异常来自 HRESULT:0x80070002)
- XML文件介绍,这也太简单了
- STM32CUBEMX(9)--ADC通过轮询方式读取,USART打印
- Linux 代理 http 和 socks 配置区别
- AES128加密解密