設想這樣一個場景:從網路流中讀取檔案到硬碟中并計算檔案的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等,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/298781.html
標籤:Java
上一篇:Hystrix 配置引數全決議
