package org.sxkj.common.utils;
|
|
import java.io.File;
|
import java.io.FileInputStream;
|
import java.io.IOException;
|
import java.io.InputStream;
|
import java.net.URL;
|
import java.security.MessageDigest;
|
import java.security.NoSuchAlgorithmException;
|
|
public class MD5Util {
|
/**
|
* 计算文件的“16位MD5”哈希值 (截取32位MD5的中间16位)
|
*
|
* @param file 要计算MD5的文件
|
* @return 文件的“16位MD5”哈希字符串,如果发生错误或无法生成32位MD5则返回null
|
*/
|
public static String get16BitMD5Checksum(File file) {
|
String fullMD5 = getFullMD5Checksum(file);
|
if (fullMD5 != null && fullMD5.length() == 32) {
|
// 截取第9到第24位 (索引8到23)
|
return fullMD5.substring(8, 24);
|
}
|
return null;
|
}
|
/**
|
* 计算文件的标准32位MD5哈希值
|
*
|
* @param file 要计算MD5的文件
|
* @return 文件的32位MD5哈希字符串,如果发生错误则返回null
|
*/
|
public static String getFullMD5Checksum(File file) {
|
if (file == null || !file.exists() || !file.isFile()) {
|
System.err.println("Invalid file provided for MD5 calculation.");
|
return null;
|
}
|
try (InputStream fis = new FileInputStream(file)) {
|
MessageDigest md = MessageDigest.getInstance("MD5");
|
byte[] buffer = new byte[8192]; // 缓冲区可以大一点,例如8KB
|
int bytesRead;
|
|
while ((bytesRead = fis.read(buffer)) != -1) {
|
md.update(buffer, 0, bytesRead);
|
}
|
|
byte[] digest = md.digest();
|
StringBuilder sb = new StringBuilder();
|
for (byte b : digest) {
|
sb.append(String.format("%02x", b));
|
}
|
return sb.toString();
|
} catch (IOException | NoSuchAlgorithmException e) {
|
e.printStackTrace();
|
return null;
|
}
|
}
|
public static String getMD5Checksum(File file) {
|
try (InputStream fis = new FileInputStream(file)) {
|
MessageDigest md = MessageDigest.getInstance("MD5");
|
byte[] buffer = new byte[1024];
|
int bytesRead;
|
|
while ((bytesRead = fis.read(buffer)) != -1) {
|
md.update(buffer, 0, bytesRead);
|
}
|
|
byte[] digest = md.digest();
|
StringBuilder sb = new StringBuilder();
|
for (byte b : digest) {
|
sb.append(String.format("%02x", b));
|
}
|
return sb.toString();
|
} catch (IOException | NoSuchAlgorithmException e) {
|
e.printStackTrace();
|
return null;
|
}
|
}
|
/**
|
* 【核心方法】从任意输入流计算 MD5 校验和。
|
* @param is 输入流
|
* @return 32位的十六进制 MD5 字符串
|
* @throws NoSuchAlgorithmException 如果 MD5 算法不可用
|
* @throws IOException 如果流读取失败
|
*/
|
private static String calculateMD5(InputStream is) throws NoSuchAlgorithmException, IOException {
|
MessageDigest md = MessageDigest.getInstance("MD5");
|
byte[] buffer = new byte[8192]; // 8KB 缓冲区
|
int bytesRead;
|
|
while ((bytesRead = is.read(buffer)) != -1) {
|
md.update(buffer, 0, bytesRead);
|
}
|
|
byte[] digest = md.digest();
|
StringBuilder sb = new StringBuilder();
|
for (byte b : digest) {
|
sb.append(String.format("%02x", b));
|
}
|
return sb.toString();
|
}
|
|
|
/**
|
* 【新增方法】从网络 URL 计算文件的 MD5 校验和。
|
* @param urlString 文件的网络地址
|
* @return 32位的十六进制 MD5 字符串,如果出错则返回 null
|
*/
|
public static String getMD5ChecksumFromUrl(String urlString) {
|
try {
|
URL url = new URL(urlString);
|
// try-with-resources 确保网络流被关闭
|
try (InputStream is = url.openStream()) {
|
return calculateMD5(is);
|
}
|
} catch (IOException | NoSuchAlgorithmException e) {
|
// MalformedURLException 是 IOException 的子类,所以会被捕获
|
e.printStackTrace();
|
return null;
|
}
|
}
|
public static String getMD5Checksum(String input) {
|
try {
|
MessageDigest md = MessageDigest.getInstance("MD5");
|
byte[] bytes = input.getBytes();
|
md.update(bytes);
|
|
byte[] digest = md.digest();
|
StringBuilder sb = new StringBuilder();
|
for (byte b : digest) {
|
sb.append(String.format("%02x", b));
|
}
|
return sb.toString();
|
} catch (NoSuchAlgorithmException e) {
|
e.printStackTrace();
|
return null;
|
}
|
}
|
}
|