如何在不额外读流的情况下计算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), 即如果执行中进行读取时,经常可能有另一执行要写入 ...
随机推荐
- Mysql5.6.44版本安装及基本配置
内容概要 存储数据的演变史 数据库软件应用史 MySQL简介 MySQL下载及安装 MySQL配置 存储数据的演变史 1.文本文件: 文件路径不固定,并且数据格式不统一 2.软件开发目录规范: 规定了 ...
- devexpress中searchLookUpEdit赋值不显示
给searchLookUpEdit进行赋值的时候使用 string str="123"; searchLookUpEdit1.EditValue = str; 一直不显示或者显示为 ...
- Multipass,本地轻量级Linux体验!
Multipass介绍 Multipass 是由Ubuntu官方提供,在Linux,MacOS和Windows上快速生成 Ubuntu虚拟机 的工具.它提供了一个简单但功能强大的CLI,可让我们在本地 ...
- ES文件传输助手1.0.0
软件下载地址 1.软件功能 与 ES文件浏览器 的快传功能 直接传输文件 支持接受文件点击预览 可以多台电脑使用该软件,从而实现电脑与电脑局域网互传文件 单个文件夹上传会递归上传该文件夹下所有文件夹与 ...
- variant conversion error for variable:v8
oracle 添加表数据报错:variant conversion error for variable:v8. 是数据类型不匹配.
- 【每日一题】【链表&头插法&ASCII码】【链表&迭代器】2022年1月28日-NC1 大数加法
描述以字符串的形式读入两个数字,编写一个函数计算它们的和,以字符串形式返回. 思路:原生链表&头插法节点值 import java.util.*; public class Solution ...
- MySQL的select for update用法
MySQL中的select for update大家应该都有所接触,但什么时候该去使用,以及有哪些需要注意的地方会有很多不清楚的地方,我把我如何使用和查询到的文档在此记录. 作用 select本身是一 ...
- CTFshow——funnyrsa2
题目如下: 题目分析: 发现n很小,可以考虑yafu分解n,或者使用在线网站,例如:http://factordb.com/.即得p,q,r.因为常规rsa只有p和q,则phi = (p -1) * ...
- MongoDB - 副本集简介
简介 在 MongoDB 中,副本集指的是一组 MongoDB 服务器实例掌管同一个数据集,实例可以在不同的机器上. 其中一个用于处理写操作的是主节点(Primary),还有多个用于保存主节点的数据副 ...
- Vue前后端分离实现登录的一个简单demo
1.建立一个Maven项目,并添加Spring相关依赖 2.编写Controller类相应的接口和配置类 LoginController类,编写接口的业务逻辑 package com.springbo ...