利用Java自带的MessageDigest来数据的Hash值非常方便,如:
Code
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
FileInputStream in = new FileInputStream(file);
FileChannel ch = in.getChannel();
MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, 0, file.length());
messageDigest.update(byteBuffer);
return messageDigest.digest();
FileInputStream in = new FileInputStream(file);
FileChannel ch = in.getChannel();
MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, 0, file.length());
messageDigest.update(byteBuffer);
return messageDigest.digest();
但如果计算较大的数据则无法监视计算进度.于是我对数据的读取和处理进行了简单的封装,以达到通过注册监听器进行进度监视的目的.
关键部分代码如下:
code
private void updateHash() throws IOException {
boolean readToEnd = readLength == 0;
byte[] bytesBuf = new byte[bufferSize];
int readLen;
while ((readToEnd || readCount < readLength)
&& (readLen = inputStream.read(bytesBuf)) > 0) {
readCount += readLen;
HashBuffer buf = new HashBuffer(bytesBuf, readLen, inputStream);
for (HashProgressInterceptor itcp : ltcps) {
itcp.bytesRead(buf, this);
}
if (!buf.isSkip()) {
for (MessageDigest md : messageDigests) {
md.update(buf.getData(), buf.getOffset(), buf.getLength());
}
}
}
byteArrayHash = new byte[messageDigests.length][];
for (int i = 0; i < messageDigests.length; i++) {
byteArrayHash[i] = messageDigests[i].digest();
}
}
boolean readToEnd = readLength == 0;
byte[] bytesBuf = new byte[bufferSize];
int readLen;
while ((readToEnd || readCount < readLength)
&& (readLen = inputStream.read(bytesBuf)) > 0) {
readCount += readLen;
HashBuffer buf = new HashBuffer(bytesBuf, readLen, inputStream);
for (HashProgressInterceptor itcp : ltcps) {
itcp.bytesRead(buf, this);
}
if (!buf.isSkip()) {
for (MessageDigest md : messageDigests) {
md.update(buf.getData(), buf.getOffset(), buf.getLength());
}
}
}
byteArrayHash = new byte[messageDigests.length][];
for (int i = 0; i < messageDigests.length; i++) {
byteArrayHash[i] = messageDigests[i].digest();
}
}
原理很简单,就是每读取一些数据就调用监听器方法并传入信息参数.
使用方法:
1.通过抽象类HashCalc的工厂方法获取实例.
2.注册监听器(如果需要监视进度).
3.调用getHexStringHash()或getByteArrayHash()取得结果,这两个方法的区别仅是结果的形式不同.第一次调用这两个方法其中之一时会进行计算并缓存结果,之后再调用将直接返回缓存中的值.
Example
import idv.takamachi660.util.hash.HashBuffer;
import idv.takamachi660.util.hash.HashCalc;
import idv.takamachi660.util.hash.HashProgressInterceptor;
import idv.takamachi660.util.hash.IHashCalc;
import java.io.File;
import java.io.IOException;
import java.security.MessageDigest;
public class FileHashDemo {
public static void main(String[] args) throws IOException {
long startTime = System.currentTimeMillis();
IHashCalc hash = HashCalc.getFileInstance(
"your file name here", "MD5", "SHA-1");
hash.setBufferSize(5242880);
// set buffer size to 5MB default value is 1MB
hash.addHashProgressInterceptor(new HashProgressInterceptor() {
@Override
public void bytesRead(HashBuffer buffer, IHashCalc calc) {
long finished = calc.getReadCount();
long total = ((File) calc.getSource()).length();
System.out.println(String.format("read %d bytes,%.2f%%", buffer
.getLength(), finished * 100.0 / total));
}
});
MessageDigest[] mds = hash.getMessageDigests();
String[] results = hash.getHexStringHash();
for (int i = 0; i < mds.length; i++) {
System.out.println(mds[i].getAlgorithm() + "=" + results[i]);
}
System.out.println("spend " + (System.currentTimeMillis() - startTime)
+ "Millis");
}
}
import idv.takamachi660.util.hash.HashCalc;
import idv.takamachi660.util.hash.HashProgressInterceptor;
import idv.takamachi660.util.hash.IHashCalc;
import java.io.File;
import java.io.IOException;
import java.security.MessageDigest;
public class FileHashDemo {
public static void main(String[] args) throws IOException {
long startTime = System.currentTimeMillis();
IHashCalc hash = HashCalc.getFileInstance(
"your file name here", "MD5", "SHA-1");
hash.setBufferSize(5242880);
// set buffer size to 5MB default value is 1MB
hash.addHashProgressInterceptor(new HashProgressInterceptor() {
@Override
public void bytesRead(HashBuffer buffer, IHashCalc calc) {
long finished = calc.getReadCount();
long total = ((File) calc.getSource()).length();
System.out.println(String.format("read %d bytes,%.2f%%", buffer
.getLength(), finished * 100.0 / total));
}
});
MessageDigest[] mds = hash.getMessageDigests();
String[] results = hash.getHexStringHash();
for (int i = 0; i < mds.length; i++) {
System.out.println(mds[i].getAlgorithm() + "=" + results[i]);
}
System.out.println("spend " + (System.currentTimeMillis() - startTime)
+ "Millis");
}
}
其他内容见doc.