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