我需要为输入流(或文件)计算校验和,以检查文件内容是否已更改。我有以下代码,虽然我使用相同的流,但每次执行都会生成不同的值。有人可以帮我做这件事吗?
public class CreateChecksum {
public static void main(String args[]) {
String test = "Hello world";
ByteArrayInputStream bis = new ByteArrayInputStream(test.getBytes());
System.out.println("MD5 checksum for file using Java : " + checkSum(bis));
System.out.println("MD5 checksum for file using Java : " + checkSum(bis));
}
public static String checkSum(InputStream fis){
String checksum = null;
try {
MessageDigest md = MessageDigest.getInstance("MD5");
//Using MessageDigest update() method to provide input
byte[] buffer = new byte[8192];
int numOfBytesRead;
while( (numOfBytesRead = fis.read(buffer)) > 0){
md.update(buffer, 0, numOfBytesRead);
}
byte[] hash = md.digest();
checksum = new BigInteger(1, hash).toString(16); //don't use this, truncates leading zero
} catch (Exception ex) {
}
return checksum;
}
}
答案 0 :(得分:5)
您正在为两个调用使用相同的流对象 - 在您调用checkSum
一次后,该流将不再有任何数据要读取,因此第二个调用将正在创建一个空流的哈希。最简单的方法是每次创建一个新流:
String test = "Hello world";
byte[] bytes = test.getBytes(StandardCharsets.UTF_8);
System.out.println("MD5 checksum for file using Java : "
+ checkSum(new ByteArrayInputStream(bytes)));
System.out.println("MD5 checksum for file using Java : "
+ checkSum(new ByteArrayInputStream(bytes)));
请注意,checkSum
中的异常处理确实需要修复,以及十六进制转换......
答案 1 :(得分:0)
文件的更改相对容易监视,每次更改(和关闭)文件时,File.lastModified()都会更改。甚至还有一个内置API可以获得有关文件系统所选更改的通知:http://docs.oracle.com/javase/tutorial/essential/io/notification.html
InputStream的hashCode不适合检测更改(没有定义InputStream应如何计算其hashCode - 很可能是它使用Object.hashCode,这意味着hashCode不依赖于除了对象标识之外的任何东西)
像尝试一样构建MD5,但每次都需要读取整个文件。如果文件很大和/或正在观看多个文件,那么这是一个性能杀手。
答案 2 :(得分:0)
你混淆了两个相关但不同的责任。
首先你有Stream
提供要阅读的东西。然后你在那个流上有一个校验和;但是,您的实现是一个static
方法调用,实际上将它与一个类分开,这意味着没有人负责维护校验和。
尝试重新处理您的解决方案
public ChecksumInputStream implements InputStream {
private InputStream in;
public ChecksumInputStream(InputStream source) {
this.in = source;
}
public int read() {
int value = in.read();
updateChecksum(value);
return value;
}
// and repeat for all the other read methods.
}
请注意,现在您只进行一次读取,校验和计算器将装饰原始输入流。
答案 3 :(得分:0)
问题出在您第一次阅读输入流之后。该pos已经到了终点。解决问题的快捷方法是
ByteArrayInputStream bis = new ByteArrayInputStream(test.getBytes()); System.out.println("使用Java的文件的MD5校验和:" + checkSum(bis));
bis = new ByteArrayInputStream(test.getBytes());
System.out.println("MD5 checksum for file using Java : " + checkSum(bis));
答案 4 :(得分:-1)
查看org / apache / commons / codec / digest / DigestUtils.html中的代码