我想使用Java来获得文件的MD5校验和。我真的很惊讶,但我还没有找到任何东西,显示如何获得一个文件的MD5校验和。

这是怎么做到的?


当前回答

从其他答案中提取想法,这里有一个简单的代码,没有第三方依赖关系(或DatatypeConverter,在最新的jdk中更长),将其生成为与md5sum工具输出兼容的十六进制字符串:

import java.io.IOException;
import java.math.BigInteger;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
...

static String calculateMD5(String path) throws IOException
{
    try {
        MessageDigest md = MessageDigest.getInstance("MD5");
        md.update(Files.readAllBytes(Paths.get(path)));
        return String.format("%032x", new BigInteger(1, md.digest())); // hex, padded to 32 chars
    } catch (NoSuchAlgorithmException ex)
    {
        throw new RuntimeException(ex); // MD5 is always available so this should be impossible
    }
}

其他回答

使用Apache Commons Codec库中的DigestUtils:

try (InputStream is = Files.newInputStream(Paths.get("file.zip"))) {
    String md5 = org.apache.commons.codec.digest.DigestUtils.md5Hex(is);
}

非常快速和干净的java方法,不依赖于外部库:

(如果你想要,只需将MD5替换为SHA-1, SHA-256, SHA-384或SHA-512)

public String calcMD5() throws Exception{
        byte[] buffer = new byte[8192];
        MessageDigest md = MessageDigest.getInstance("MD5");

        DigestInputStream dis = new DigestInputStream(new FileInputStream(new File("Path to file")), md);
        try {
            while (dis.read(buffer) != -1);
        }finally{
            dis.close();
        }

        byte[] bytes = md.digest();

        // bytesToHex-method
        char[] hexChars = new char[bytes.length * 2];
        for ( int j = 0; j < bytes.length; j++ ) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = hexArray[v >>> 4];
            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
        }

        return new String(hexChars);
}

我最近不得不为一个动态字符串这样做,MessageDigest可以以多种方式表示散列。为了获得文件的签名,就像你会得到md5sum命令,我必须做这样的事情:

try {
   String s = "TEST STRING";
   MessageDigest md5 = MessageDigest.getInstance("MD5");
   md5.update(s.getBytes(),0,s.length());
   String signature = new BigInteger(1,md5.digest()).toString(16);
   System.out.println("Signature: "+signature);

} catch (final NoSuchAlgorithmException e) {
   e.printStackTrace();
}

这显然没有回答你关于如何专门为一个文件做这件事的问题,上面的答案很好地处理了这个问题。我只是花了很多时间使和看起来像大多数应用程序显示它,并认为您可能会遇到同样的麻烦。

如果使用ANT进行构建,这非常简单。将以下内容添加到build.xml中:

<checksum file="${jarFile}" todir="${toDir}"/>

其中jarFile是要针对其生成MD5的JAR, toDir是要放置MD5文件的目录。

更多信息请点击这里。

com.google.common.hash API提供:

为所有哈希函数提供统一的用户友好的API murmur3的32位和128位种子实现 Md5()、sha1()、sha256()、sha512()适配器,只需更改一行代码就可以在这些适配器之间切换。 goodFastHash(int bits),用于当你不关心你使用什么算法时 HashCode实例的通用实用程序,如combineOrdered / combineUnordered

阅读用户指南(IO解释,哈希解释)。

对于您的用例,Files.hash()计算并返回文件的摘要值。

例如,sha-1摘要计算(将sha-1更改为MD5以获得MD5摘要)

HashCode hc = Files.asByteSource(file).hash(Hashing.sha1());
"SHA-1: " + hc.toString();

请注意,crc32比md5快得多,所以如果您不需要加密安全的校验和,请使用crc32。还要注意,md5不应该用来存储密码之类的东西,因为它很容易被暴力破解,对于密码,应该使用bcrypt、scrypt或sha-256来代替。

对于使用散列的长期保护,默克尔签名方案增加了安全性,由欧盟委员会赞助的后量子密码学研究小组建议使用这种密码技术来长期保护量子计算机(参考)。

请注意,crc32的碰撞率比其他的更高。