我想使用Java获取文件的MD5校验和。但是我很惊讶,我找不到任何展示如何获取文件的MD5校验和的资料。
请问该怎么做?
我想使用Java获取文件的MD5校验和。但是我很惊讶,我找不到任何展示如何获取文件的MD5校验和的资料。
请问该怎么做?
有一个输入流装饰器java.security.DigestInputStream
,可以在正常使用输入流的同时计算摘要,而无需对数据进行额外的读取。
MessageDigest md = MessageDigest.getInstance("MD5");
try (InputStream is = Files.newInputStream(Paths.get("file.txt"));
DigestInputStream dis = new DigestInputStream(is, md))
{
/* Read decorated stream (dis) to EOF as normal... */
}
byte[] digest = md.digest();
is
声明为了InputStream
还是FileInputStream
?听起来像是你使用了FileInputStream
,导致了这个错误。 - erickson使用Apache Commons Codec库中的DigestUtils:
try (InputStream is = Files.newInputStream(Paths.get("file.zip"))) {
String md5 = org.apache.commons.codec.digest.DigestUtils.md5Hex(is);
}
FileInputStream fis = new FileInputStream(new File(filePath)); byte data[] = org.apache.commons.codec.digest.DigestUtils.md5(fis); char md5Chars[] = Hex.encodeHex(data); String md5 = String.valueOf(md5Chars);
- Dmitry_L在Real's Java-How-to网站上有一个例子,使用MessageDigest类。
请查看该页面以获取使用CRC32和SHA-1的示例。
import java.io.*;
import java.security.MessageDigest;
public class MD5Checksum {
public static byte[] createChecksum(String filename) throws Exception {
InputStream fis = new FileInputStream(filename);
byte[] buffer = new byte[1024];
MessageDigest complete = MessageDigest.getInstance("MD5");
int numRead;
do {
numRead = fis.read(buffer);
if (numRead > 0) {
complete.update(buffer, 0, numRead);
}
} while (numRead != -1);
fis.close();
return complete.digest();
}
// see this How-to for a faster way to convert
// a byte array to a HEX string
public static String getMD5Checksum(String filename) throws Exception {
byte[] b = createChecksum(filename);
String result = "";
for (int i=0; i < b.length; i++) {
result += Integer.toString( ( b[i] & 0xff ) + 0x100, 16).substring( 1 );
}
return result;
}
public static void main(String args[]) {
try {
System.out.println(getMD5Checksum("apache-tomcat-5.5.17.exe"));
// output :
// 0bb2827c5eacf570b6064e24e0e6653b
// ref :
// http://www.apache.org/dist/
// tomcat/tomcat-5/v5.5.17/bin
// /apache-tomcat-5.5.17.exe.MD5
// 0bb2827c5eacf570b6064e24e0e6653b *apache-tomcat-5.5.17.exe
}
catch (Exception e) {
e.printStackTrace();
}
}
}
com.google.common.hash API 提供:
阅读用户指南(IO Explained,Hashing Explained)。
对于您的用例,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的碰撞率比其他算法高。Files.hash()
已标记为过时的方法,推荐使用:Files.asByteSource(file).hash(Hashing.sha1())
。 - erkfel使用nio2(Java 7+)和无外部库:
byte[] b = Files.readAllBytes(Paths.get("/path/to/file"));
byte[] hash = MessageDigest.getInstance("MD5").digest(b);
为了将结果与预期校验和进行比较:
String expected = "2252290BC44BEAD16AA1BF89948472E8";
String actual = DatatypeConverter.printHexBinary(hash);
System.out.println(expected.equalsIgnoreCase(actual) ? "MATCH" : "NO MATCH");
Guava 现在提供了一个新的、一致的哈希 API,比 JDK 提供的各种哈希 API 更加用户友好。请参阅 哈希解释。对于文件,你可以轻松获取 MD5 摘要、CRC32(使用14.0+版本)或其他许多哈希值:
HashCode md5 = Files.hash(file, Hashing.md5());
byte[] md5Bytes = md5.asBytes();
String md5Hex = md5.toString();
HashCode crc32 = Files.hash(file, Hashing.crc32());
int crc32Int = crc32.asInt();
// the Checksum API returns a long, but it's padded with 0s for 32-bit CRC
// this is the value you would get if using that API directly
long checksumResult = crc32.padToLong();
Files.hash
已被弃用,请使用Files.asByteSource(new File("")).hash(Hashing.md5())
。 - RedShift好的。我必须补充一点。对于那些已经具有Spring和Apache Commons依赖项或计划添加它们的人来说,以下是一行实现:
Ok. 我需要补充一句话。对于那些已经有Spring和Apache Commons依赖项或者打算添加这些依赖项的人来说,可以使用以下一行代码实现:
DigestUtils.md5DigestAsHex(FileUtils.readFileToByteArray(file))
只针对Apache commons的选项(感谢@duleshi):
DigestUtils.md5Hex(FileUtils.readFileToByteArray(file))
希望这能帮助到某个人。
DigestUtils.md5Hex(FileUtils.readFileToByteArray(file))
。 - duleshiSpring 5
中,您可以使用 DigestUtils.md5Digest(InputStream inputStream)
计算 MD5 摘要,以及使用 DigestUtils.md5DigestAsHex(InputStream inputStream)
获取十六进制字符串表示的 MD5 摘要方法,而无需将整个文件读入内存。 - Mike Shauneu使用Java 7,不依赖于第三方库的简单方法
String path = "your complete file path";
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(Files.readAllBytes(Paths.get(path)));
byte[] digest = md.digest();
如果您需要打印此字节数组,请按如下方式使用。System.out.println(Arrays.toString(digest));
如果您需要从此摘要中获取十六进制字符串,请按以下方式使用。String digestInHex = DatatypeConverter.printHexBinary(digest).toUpperCase();
System.out.println(digestInHex);
其中DatatypeConverter是javax.xml.bind.DatatypeConverter
toUpperCase
? - EdgeCaseBerg最近我不得不为一个动态字符串做这个,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();
}
显然,这并没有回答你如何针对文件具体实现的问题,上面的答案已经很好地解决了这个问题。我刚刚花费了很多时间让总和看起来像大多数应用程序的显示方式,并且我想你可能会遇到同样的麻烦。
.toString(16)
会丢弃前导零。String.format("%032x", ...)
可能更好。 - Haroldpublic static void main(String[] args) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5");
FileInputStream fis = new FileInputStream("c:\\apache\\cxf.jar");
byte[] dataBytes = new byte[1024];
int nread = 0;
while ((nread = fis.read(dataBytes)) != -1) {
md.update(dataBytes, 0, nread);
};
byte[] mdbytes = md.digest();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < mdbytes.length; i++) {
sb.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16).substring(1));
}
System.out.println("Digest(in hex format):: " + sb.toString());
}
或者你可以获得更多信息 http://www.asjava.com/core-java/java-md5-example/