Java 获取文件Md5的方法
·
用Java实现获取文件md5 跟linux md5Sum 一样结果的代码,如下:
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* 文件 MD5 工具类(实用版)
* 特性:1. 分片读取大文件,避免内存溢出;2. 完善的异常处理;3. 支持空文件/小文件;4. 输出标准 32 位十六进制字符串
*/
public class FileMd5Util {
// 缓冲区大小(8KB,平衡性能与内存占用,可根据需求调整)
private static final int BUFFER_SIZE = 8192;
/**
* 获取文件的 MD5 值
* @param filePath 文件绝对路径/相对路径
* @return 32 位小写 MD5 字符串;若文件不存在/不可读/异常,返回 null
*/
public static String getFileMd5(String filePath) {
// 1. 校验文件路径合法性
if (filePath == null || filePath.trim().isEmpty()) {
System.err.println("文件路径不能为空");
return null;
}
File file = new File(filePath);
// 2. 校验文件是否存在、是否为文件(非目录)、是否可读
if (!file.exists()) {
System.err.println("文件不存在:" + filePath);
return null;
}
if (!file.isFile()) {
System.err.println("不是文件(是目录):" + filePath);
return null;
}
if (!file.canRead()) {
System.err.println("文件不可读(权限不足):" + filePath);
return null;
}
MessageDigest md5Digest = null;
FileInputStream fis = null;
try {
// 3. 初始化 MD5 消息摘要
md5Digest = MessageDigest.getInstance("MD5");
fis = new FileInputStream(file);
// 4. 分片读取文件,更新摘要(避免大文件占用过多内存)
byte[] buffer = new byte[BUFFER_SIZE];
int readLen;
while ((readLen = fis.read(buffer)) != -1) {
// 仅更新实际读取到的字节(避免缓冲区剩余无效数据影响结果)
md5Digest.update(buffer, 0, readLen);
}
// 5. 生成 16 字节的 MD5 摘要,转换为 32 位十六进制字符串
byte[] md5Bytes = md5Digest.digest();
return bytesToHex(md5Bytes);
} catch (NoSuchAlgorithmException e) {
// 理论上不会触发(MD5 是 Java 标准算法)
System.err.println("MD5 算法不支持(异常):" + e.getMessage());
return null;
} catch (IOException e) {
System.err.println("读取文件失败:" + e.getMessage() + ",文件路径:" + filePath);
return null;
} finally {
// 6. 关闭流(避免资源泄漏)
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
System.err.println("关闭文件流失败:" + e.getMessage());
}
}
}
}
/**
* 将字节数组转换为 32 位小写十六进制字符串(标准 MD5 格式)
* @param bytes 消息摘要字节数组(MD5 为 16 字节)
* @return 32 位小写十六进制字符串
*/
private static String bytesToHex(byte[] bytes) {
StringBuilder hexBuilder = new StringBuilder();
for (byte b : bytes) {
// 转换为无符号整数(0-255)
int unsignedByte = b & 0xFF;
// 小于 16 补前导 0(保证每字节对应两位十六进制)
if (unsignedByte < 16) {
hexBuilder.append("0");
}
// 转换为十六进制字符串(小写)
hexBuilder.append(Integer.toHexString(unsignedByte));
}
return hexBuilder.toString();
}
// ------------------------------ 测试示例 ------------------------------
public static void main(String[] args) {
// 测试 1:小文件(当前项目根目录下的 test.txt)
String smallFileMd5 = getFileMd5("test.txt");
System.out.println("小文件 MD5:" + (smallFileMd5 != null ? smallFileMd5 : "获取失败"));
// 测试 2:大文件(示例路径,需替换为实际文件路径)
String largeFileMd5 = getFileMd5("D:/下载/大型软件.iso");
System.out.println("大文件 MD5:" + (largeFileMd5 != null ? largeFileMd5 : "获取失败"));
// 测试 3:与 Linux md5sum 对比(确保结果一致)
String linuxFileMd5 = getFileMd5("/home/user/test.txt");
System.out.println("Linux 环境文件 MD5:" + (linuxFileMd5 != null ? linuxFileMd5 : "获取失败"));
}
}
加粗样式核心特性(实用关键)
- 大文件支持:采用 8KB 缓冲区 分片读取,即使是 GB 级文件也不会内存溢出(避免直接读取整个文件到内存)。
- 完善的校验:
校验文件路径非空、文件存在、是文件(非目录)、可读(权限校验)。
捕获文件读取异常、算法不支持异常(理论上不会触发)。 - 标准输出:输出 32 位小写十六进制字符串,与 Linux md5sum、Windows certutil -hashfile 文件名 MD5 结果完全一致,可直接用于跨平台文件校验。
- 资源安全:使用 finally 块确保文件流关闭,避免资源泄漏。
- 大文件处理慢:增大 BUFFER_SIZE(如 65536 即 64KB),减少 I/O 次数
- 易用性:单方法调用 getFileMd5(文件路径) 即可获取结果,返回 null 时可通过控制台日志查看失败原因。
- 使用方法
// 相对路径(项目根目录)
String md5 = FileMd5Util.getFileMd5("test.txt");
// 绝对路径(Windows)
String md5 = FileMd5Util.getFileMd5("C:/Users/xxx/Documents/data.csv");
// 绝对路径(Linux/Mac)
String md5 = FileMd5Util.getFileMd5("/home/xxx/data.csv");
更多推荐


所有评论(0)