先说说 Java 生成 MD5 的原理
Java 生成 MD5 值,本质上都是通过MessageDigest
类来实现的。
一共分为四步:
-
通过
MessageDigest.getInstance("MD5")
方法来获取一个MessageDigest
实例。这是一个工厂方法,你也可以创建其他算法的实例。 -
通过
update
方法来传入字节数组,并根据该数组更新摘要。 -
使用
digest()
计算并返回byte[]
格式的哈希值,并重置摘要。 -
用各种办法将
byte[]
格式的哈希值转为16进制字符串。
翻译成代码如下:
public String getMD5String(String s) throws NoSuchAlgorithmException {
// 创建md5实例
MessageDigest messagedigest = MessageDigest.getInstance("MD5");
// 更新摘要
messagedigest.update(s.getBytes());
// 计算哈希并返回
byte[] digest = messagedigest.digest();
// 将摘要转换成16进制字符串
return bufferToHex(digest);
}
愣着干嘛,用轮子呀
话说我又要算字符串的 MD5 值,也要算文件的 MD5 值,而且转 16 进制字符串,这些我都要自己写?
直接用轮子吧。
常用的是这两个工具类:
public void getMD5(String str) {
// Spring的工具类
org.springframework.util.DigestUtils.md5DigestAsHex(str.getBytes());
// commons-codec包的工具类
org.apache.commons.codec.digest.DigestUtils.md5Hex(str);
}
如果你不是 Spring 工程,且因为莫名其妙不能随便引用新的jar包,那么我建议直接把org.springframework.util.DigestUtils
拷贝出来自己用就好了。不建议拷贝commons-codec
包的工具类,因为额外引用的类太多。
生成文件夹的 MD5 值
现有的工具类没有直接计算文件夹 MD5 值的方法,而且本身文件夹也没法计算 MD5 值吧。
但是一定要计算,那我们可以自己定义一个算法。很简单,如果是文件夹,则遍历文件夹下的全部文件,对每个文件都计算一次 MD5 值,放到一个列表里。最后把列表中的 MD5 值拼在一起生成一个新的 MD5 值作为文件夹的 MD5 值来使用就好了。
代码如下(直接用了 Spring 的DigestUtils
工具类):
/**
* 获取文件/文件夹md5信息
* 文件夹md5生成逻辑:遍历文件夹下的全部文件,并计算文件的md5值。
* 之后将所有文件的md5值拼接在一起去生成一个新的md5值作为文件夹的md5值。
*
* @param file
* @return
* @throws IOException
* @throws NoSuchAlgorithmException
*/
public String getFileMD5(File file) throws IOException {
// 计算文件夹的md5值时,用于存放文件夹下每个文件的md5值
Set<String> md5List = new HashSet<>();
fillMD5List(file, md5List);
if (md5List.isEmpty()) {
logger.info("路径不存在,不计算md5值,路径:" + file.getPath());
return "";
}
if (md5List.size() == 1) {
return new ArrayList<>(md5List).get(0);
}
StringBuilder sb = new StringBuilder();
for (String s : md5List) {
sb.append(s);
}
return DigestUtils.md5DigestAsHex(sb.toString().getBytes());
}
public void fillMD5List(File file, Set<String> md5List) throws IOException {
if (file == null || !file.exists()) {
return;
}
if (file.isDirectory()) {
File[] f = file.listFiles();
if (f != null) {
for (File value : f) {
fillMD5List(value, md5List);
}
}
} else {
String md5 = DigestUtils.md5DigestAsHex(new FileInputStream(file));
md5List.add(md5);
}
}