3.2.4 DigestInputStream
通过MessageDigest类,我们实现了消息摘要算法,但是通过字节或字节数组的方式完成摘要操作,使用起来并不是很方便,因此有了消息摘要流,包含消息摘要输入流和消息摘要输出流。
DigestInputStream类继承了FilterInputStream类,可以通过读取输入流的方式完成摘要更新,因此我们称它为消息摘要输入流,在指定的读操作方法内部完成MessageDigest类的update()方法。
//提供一个输入流,针对所有通过该流的数据计算出相应的消息摘要。
public class DigestInputStream
extends FilterInputStream
❑方法详述
可以通过以下方法实例化对象:
/使用指定的InputStream和MessageDigest创建一个DigestInputStream实例。/
public DigestInputStream(InputStream stream, MessageDigest digest)
当需要更新MessageDigest对象时,可以使用如下方法:
//将指定的MessageDigest与此流相关联。
public void setMessageDigest(MessageDigest digest)
与之相对应的,获得MessageDigest对象可以用以下方法:
//返回与此流关联的MessageDigest。
public MessageDigest getMessageDigest()
当通过下述方法关闭摘要功能后,DigestInputStream就变成了一般的输入流:
//开启或关闭摘要功能。
public void on(boolean on)
请注意要使用下述方法更新摘要信息时,一定要确保DigestInputStream开启摘要功能:
//读取字节并更新消息摘要(如果开启了摘要功能)。
public int read()
//读入byte数组并更新消息摘要(如果开启了摘要功能)。
public int read(byte[]b, int off, int len)
上述方法将调用MessageDigest的update()方法完成摘要更新,在此之后可以通过getMessageDigest()方法获得MessageDigest对象,并执行MessageDigest对象的digest()方法完成摘要操作。
摘要DigestInputStream类的相关源码,如代码清单3-3所示。
代码清单3-3 DigestInputStream类读操作部分源代码
public int read()throws IOException{
int ch=in.read();
if(on&&ch!=-1){
digest.update((byte)ch);
}
return ch;
}
public int read(byte[]b, int off, int len)throws IOException{
int result=in.read(b, off, len);
if(on&&result!=-1){
digest.update(b, off, result);
}
return result;
}
除上述方法外,通常还用到以下方法:
//打印此摘要输入流及其关联的消息摘要对象的字符串表示形式。
public String toString()
❑实现示例
我们可以通过如下方式使用该消息摘要输入流,如代码清单3-4所示。
代码清单3-4 MD5算法摘要输入流处理
//待做消息摘要操作的原始信息。
byte[]input="md5".getBytes();
//初始化MessageDigest对象,将使用MD5算法。
MessageDigest md=MessageDigest.getInstance("MD5");
//构建DigestInputStream对象。
DigestInputStream dis=new DigestInputStream(new ByteArrayInputStream(input),md);
//流输入
dis.read(input,0,input.length);
//获得摘要信息
byte[]output=dis.getMessageDigest().digest();
//关闭流
dis.close();