利用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();  

 

但如果计算较大的数据则无法监视计算进度.于是我对数据的读取和处理进行了简单的封装,以达到通过注册监听器进行进度监视的目的.

关键部分代码如下:

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();
    }
    }

 

原理很简单,就是每读取一些数据就调用监听器方法并传入信息参数.


使用方法:

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");
    }
}

 

 

 

其他内容见doc.

/Files/takamachi660/Java_HashTools.zip

posted on 2010-01-10 19:10  高町⑥⑥○  阅读(1874)  评论(1编辑  收藏  举报