用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");
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐