如何在不额外读流的情况下计算md5值
设想这样一个场景:从网络流中读取文件到硬盘中并计算文件的md5值。通常的做法是先将文件保存下来,再计算文件的md5,但这样会一共会出现三次I/O,一次网络I/O,两次磁盘I/O。
导致额外磁盘I/O的写法
import org.apache.commons.io.IOUtils;
import org.springframework.util.DigestUtils;
import java.io.*;
import java.net.URL;
public class Main {
public static void main(String[] args) throws Exception {
//下载文件,百度logo
URL url = new URL("https://www.baidu.com/img/flexible/logo/plus_logo_web_2.png");
File file = new File("file.png");
try (InputStream in = url.openStream(); OutputStream out = new FileOutputStream(file)) {
IOUtils.copy(in, out);
}
//计算md5
try (FileInputStream fileInputStream = new FileInputStream(file)) {
//计算md5
String md5 = DigestUtils.md5DigestAsHex(fileInputStream);
System.out.println(md5);
}
}
}
上面的代码使用spring提供的MD5工具类,将流作为参数传入,直接返回md5值,这样的工具用起来简单方便,是很多人的首选。
然而,java提供的md5工具并没有这样的接口,java提供MessageDigest工具类计算md5时只提供了较为底层的接口,因为不好用,很多人忽视了它。
下面的例子中,下载文件并计算md5只用到一次磁盘I/O
import java.io.*;
import java.math.BigInteger;
import java.net.URL;
import java.security.MessageDigest;
public class Main {
public static void main(String[] args) throws Exception {
//下载文件,百度logo
URL url = new URL("https://www.baidu.com/img/flexible/logo/plus_logo_web_2.png");
File file = new File("file.png");
//计算md5
MessageDigest md5Digest = MessageDigest.getInstance("md5");
try (InputStream in = url.openStream(); OutputStream out = new FileOutputStream(file)) {
int len;
byte[] buffer = new byte[1024 * 4];
while ((len = in.read(buffer)) != -1) {
//更新散列值
md5Digest.update(buffer, 0, len);
//写入文件
out.write(buffer, 0, len);
}
}
//散列值数组
byte[] digest = md5Digest.digest();
//1表明这是无符号整数
BigInteger bigInteger = new BigInteger(1, digest);
//以16进制的形式输出
System.out.println(bigInteger.toString(16));
}
}
以上就是避免额外读流的方式计算md5,当然也可以推广到其他hash算法上,例如sha256等。
如何在不额外读流的情况下计算md5值的更多相关文章
- 关于datagridview中checkbox列在选中行的情况下无法操作值
这几天做项目的时候碰到了个小问题,在datagridview中实现对checkbox列的全选和反选功能.代码如下 //全选 if (dataGrid ...
- Java中只有按值传递,没有按引用传递!(两种参数情况下都是值传递)
今天,我在一本面试书上看到了关于java的一个参数传递的问题: 写道 java中对象作为参数传递给一个方法,到底是值传递,还是引用传递? 我毫无疑问的回答:“引用传递!”,并且还觉得自己对java的这 ...
- 知道一个数组某个index对应的值 不知道下标的情况下删除该值
for (index,item) in Arr.enumerated() { if item == item { Arr.remove(at: index) } } 更好的方法是用数组的filter尾 ...
- 字符串、字节数组、流之间的相互转换以及文件MD5的计算
using System; using System.IO; using System.Security.Cryptography; using System.Text; namespace myMe ...
- 条目二十一《总是让比较函数在等值情况下返回false》
条目二十一<总是让比较函数在等值情况下返回false> 这条目对序列容器是不适合的,因为序列容器就是通过等值判断来比较的. 对于关联容器来说,比较是等价比较,所以要注意等值的时候,比较子的 ...
- 手写node可读流之流动模式
node的可读流基于事件 可读流之流动模式,这种流动模式会有一个"开关",每次当"开关"开启的时候,流动模式起作用,如果将这个"开关"设置成 ...
- 可读流 - nodejs stream总结
可读流 包含的事件:data,readable,end,close ,error,pause,resume 常用方法:resume,read,pipe,pause 客户端的 HTTP 响应 服务器的 ...
- 极简 Node.js 入门 - 4.3 可读流
极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...
- node中的可读流和可写流
javascript的一个不足之处是不能处理二进制数据,于是node中引入了Buffer类型.这个类型以一个字节(即8位)为单位,给数据分配存储空间.它的使用类似于Array,但是与Array又有不同 ...
- JDK1.8 StampedLock: 解决ReentrantReadWriteLock在读多写少情况下,写线程饥饿问题
ReentrantReadWriteLock 在沒有任何读写锁时,才可以取得写入锁,这可用于实现了悲观读取(Pessimistic Reading), 即如果执行中进行读取时,经常可能有另一执行要写入 ...
随机推荐
- Crony 一个基于Go语言实现的分布式定时任务管理平台
crony - 分布式定时任务管理平台 1. 基本介绍 1.1 项目背景 项目中存在许多定时任务,很多代码写法都是采取见缝插针式的写法或者直接丢到task服务里面写,存在以下问题 服务多实例时执行定时 ...
- Objects.requireNonNull的意义是什么
Objects.requireNonNull方法的源码是这样: public static <T> T requireNonNull(T obj) { if (obj == null) t ...
- JAVA-面向对象之对象拷贝
Java 中的数据类型分为基本数据类型和引用数据类型.对于这两种数据类型,在进行赋值操作.用作方法参数或返回值时,会有值传递和引用(地址)传递的差别. Map对象 测试01-等号赋值: @Test p ...
- [论文阅读] 颜色迁移-Linear Monge-Kantorovitch(MKL)
[论文阅读] 颜色迁移-Linear Monge-Kantorovitch(MKL) 文章: The Linear Monge-Kantorovitch Linear Colour Mapping f ...
- python 爬取豆瓣电影评论,并进行词云展示
python 爬取豆瓣电影评论,并进行词云展示 本文旨在提供爬取豆瓣电影<我不是药神>评论和词云展示的代码样例 1.分析URL 2.爬取前10页评论 3.进行词云展示 1.分析URL 我不 ...
- Flutter和Rust如何优雅的交互
前言 文章的图片链接都是在github上,可能需要...你懂得:本文含有大量关键步骤配置图片,强烈建议在合适环境下阅读 Flutter直接调用C层还是蛮有魅力,想想你练习C++,然后直接能用flutt ...
- 自研ORM框架 实现类似EF Core Include 拆分查询 支持自定义条件、排序、选择
Baozi, I'm Mr.Zhong I like to brush TikTok, I know that anchors like to call it that, haha!Recently, ...
- JavaScript:函数:如何声明和调用函数?
首先,理解什么是函数? 通俗的说,函数就是用大括号括起来的一组JS语句的集合体,是一个代码块,表达一种行为逻辑. 当我们调用函数的时候,我们就是在执行这一组JS语句. 然后,确定一点,在JS中,函数也 ...
- vlc qt player 播放器开发实例
(一)VLC-Qt下载 官网地址:https://vlc-qt.tano.si/ Github 地址:https://github.com/vlc-qt 示例地址:https://github.com ...
- 大数据 - DWS层 业务实现
统计主题 需求指标[ADS] 输出方式 计算来源 来源层级 访客[DWS] pv 可视化大屏 page_log 直接可求 dwd UV(DAU) 可视化大屏 需要用 page_log 过滤去重 dwm ...