龙空技术网

开发实践(1)——计算文件的MD5值

易善知 178

前言:

现时大家对“md5例题”可能比较看重,同学们都想要了解一些“md5例题”的相关资讯。那么小编也在网上汇集了一些对于“md5例题””的相关内容,希望各位老铁们能喜欢,大家快快来学习一下吧!

本节内容讨论计算文件的MD5值的相关问题。

计算文件的MD5值,不是个难题,在网上搜索,有比较多的示例程序。示例1是通过读取文件内容 ,计算MD5值;示例2在保存文件的过程中,计算MD5值。共同的特点是,计算MD5值需要对文件中的所有字节进行计算。

示例1:读文件计算MD5值

MessageDigest md5 = MessageDigest.getInstance("MD5");FileInputStream inputStream = new FileInputStream(new File("/var/files/xx.file"));byte[] buffer = new byte[8192]; // 缓冲区大小int length = 0;while ((length = inputStream.read(buffer)) > 0) { md5.update(buffer, 0, length);}String md5Value = new String(Hex.encodeHex(md5.digest()));

示例2、上传文件计算MD5值

MessageDigest md5 = MessageDigest.getInstance("MD5");InputStream inputStream = part.getInputStream();FileOutputStream outStream = new FileOutputStream(new File("/var/files/xx.file"));byte[] buffer = new byte[8192]; // 缓冲区大小int length = 0;while ((length = inputStream.read(buffer)) > 0) { md5.update(buffer, 0, length); outStream.write(buffer, 0, length);}String md5Value = new String(Hex.encodeHex(md5.digest()));

示例3,上传文件保存到S3

InputStream inputStream = request.getInputStream();s3Client.uploadToS3(inputStream);

实例3的代码,把上传的文件保存到S3上,s3Client以inputStream作为参数 ,非常简单。但是计算MD5值,有些无从下手了。我们知道,对于inputStream来说,只能读取一次,所以不能在upload前从流中读数据并计算MD5值,同时在上传成功后,也不能再次从流中读取数据。

方案一:文件缓冲。

为了解决这个这个问题,通过实例2的思路,先保存文件,保存过程中计算MD5值;然后以文件路径为参数创建FileInputStream,作为s3Client的参数,把文件保存到S3。

优点:实现思路简单,代码也不复杂,非常适合初学者。

缺点:多了一次文件IO,使得单个文件的处理时间变长,降低了系统的处理性能。同时,也增加了对本地硬盘的访问压力。

方案二:内存缓冲。

既然利用文件,效率比较低,通过内存缓冲区可以解决速度的问题。可以ByteArrayOutputStream和ByteArrayInputStream这对stream实现。

实例4,通过内存缓冲区

MessageDigest md5 = MessageDigest.getInstance("MD5");InputStream inputStream = part.getInputStream();ByteArrayOutputStream outStream = new ByteArrayOutputStream((int)part.getSize());byte[] buffer = new byte[8192];int length = 0;while ((length = inputStream.read(buffer)) > 0) { md5.update(buffer, 0, length); outStream.write(buffer, 0, length);}String md5Value = new String(Hex.encodeHex(md5.digest()));ByteArrayInputStream inStream = new ByteArrayInputStream(outStream.toByteArray());s3Client.uploadToS3(inStream);

优点:通过内存缓冲,没有文件IO,执行效率高。

缺点:小文件还好,大文件加载到内存,内存占用过大。极端情况下 ,一个大文件就能把内存消耗干净。

方案三:无缓冲。

无论是文件缓冲,还是内存缓冲,都需要缓存整个文件,都不是理想的解决方案。s3Client需要的参数是一个InputStream,是否可以给它构造一个InputStream呢?按照这个思路,利用装饰器设计模式,自定义一个InputStreamWrapper,在读取数据时,计算MD5值。既没有文件缓冲,没有内存缓冲,完美的解决了我们的问题。具体实现如下:

public class InputStreamWrapper extends InputStream { private InputStream inputStream; private MessageDigest messageDigest; InputStreamWrapper(InputStream inputStream) throws NoSuchAlgorithmException { this.inputStream = inputStream; this.messageDigest = MessageDigest.getInstance("MD5"); } @Override public int read(byte[] bytes) throws IOException { int size = inputStream.read(bytes); if (size > 0) { messageDigest.update(bytes, 0, size); } return size; } @Override public int read(byte bytes[], int off, int len) throws IOException { int size = inputStream.read(bytes, off, len); if (size > 0) { messageDigest.update(bytes, 0, size); } return size; } public String getMD5() { return Hex.encodeHexString(messageDigest.digest()); }}
InputStream inputStream = request.getInputStream();InputStreamWrapper inputStreamWapper = new InputStreamWrapper(inputStream);s3Client.uploadToS3(inputStreamWapper);String md5Value = inputStreamWapper.getMD5();

标签: #md5例题