当一个任务下载完成之后,肯定得考虑文件是否下载完整。所以就会涉及到文件校验,常用的当然还是通过MD5摘要来校验。
习惯性的想到的就是,从服务器端拿到资源文件的MD5码,然后不断的读取本地文件并调用MessageDigest.update(byte) 方法来生成摘要,然后与服务器端的MD5码比较。
但是如果文件过大的话,仅生成本地文件的MD5码就会浪费大量的时间。
其实本身java中就提供了一个DigestInputStream 的类,就可以生成本地文件的MD5码(当然,也可以使用DigestOutputStream来生成 。
这个流在在读取资源文件的过程中就update 了Digest(当然 DigestOutputStream 即write方法调用的过程中更新了摘要)
MessageDigest digest = MessageDigest.getInstance("MD5");
FileInputStream in = new FileInputStream(new File(filePath));
DigestInputStream stream = new DigestInputStream(in, digest);
byte[] bs = new byte[1024];
while((stream.read(bs))!=-1){
//TODO
}
// 循环结束后,则digest已经更新完毕了。
System.out.println((stream.getMessageDigest())==digest);//输出true 他还是原来的他.
当然,这个digest在调用digest方法之前,还是可以继续更新的。 一个很使用的场景就是断点续传。 通过前半部分代码,可以已下载完成的文件内容生成摘要,然后从服务器上的资源文件对应位置获取到输入流的时候,继续使用这个digest来进一步更新。当下载完成之后,则这个摘要也更新完毕,就可以直接比较了。
当然这个包装流的封装实现也非常简单。只在read 或者write 方法的byte的时候,调用MessageDigest.update(byte) 也是一样的