设想这样一个场景:从网络流中读取文件到硬盘中并计算文件的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值,这样的工具用起来简单方便,是很多人的首选。 下面的例子中,下载文件并计算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等。
|
|