我的Java开发学习之旅------>工具类:Java获取字符串和文件进行MD5值

ps:这几天本人用百度云盘秒传了几部大片到云盘上,几个G的文件瞬秒竟然显示“上传成功”!这真让我目瞪口呆,要是这样的话,那得多快的网速,这绝对是不可能的,也许这仅是个假象。百度了一下才发现所谓的“秒传”是常见的“忽略式”上传方式,就是您上传了一个文件名为111.exe,MD5为一个数,有一个网友以前也上传一个叫222.exe,MD5和您上传的文件MD5码一模一样,所以这个文件上传到服务器上的时间就很短了,这是因为别人上传过这个文件,您上传这个文件,服务器上有这个文件了,所以只需要把这个文件复制一份到您的网盘上就可以了。

秒传的原理详细解释  

上传到网盘的每个文件,服务器都会校验MD5码。如果这个您上传的文件MD5码与已经存在于服务器里的文件的MD5码相同的话,网盘服务器将会判断成为重复文件,只需要复制副本保存在网盘上即可,无需重新保存,因为有过目前这个文件,于是很快完成上传任务,并在有人需要下载的时候将原有的该文件的下载地址放出。这样实现了服务器的高效运作。

怎样不秒传?  

把你要上传的东西压缩成RAR,东西上传,服务器会先做MD5校验,如果服务器上有一样的东西,它就直接给你个新地址,其实你下载的都是服务器上的同一个文件,想要不秒传,其实只要让MD5改变,就是对文件本身做一下修改(改名字不行),例如一个文本文件,你多加几个字,MD5就变了,就不会秒传了。  但是有些文件我们不好改变,也不想改变,那其实只要压缩一下,MD5就变了,而下载的人也能获得最原始的资料,不过就是加压要花费一点时间。

下面来学习学习MD5的相关知识,MD5 即Message-Digest Algorithm 5(信息-摘要算法5 ),是一种用于产生数字签名的单项散列算 法,在1991年由MIT Laboratory for Computer Science(MIT计算机科学实验室)和RSA Data Security Inc(RSA数据安全公司)的Ronald L. Rivest教授开发出来,经由MD2、MD3和MD4发展而来。MD5算法的使用不需要支付任何版权费用。它的作用是让大容量信息在用数字签名软件签私人密匙前被"压缩"成一种保密的格式(将一个任意长度的“字节串”通过一个不可逆的字符串变换算法变换成一个128bit的大整数
,换句话说就是,即使你看到源程序和算法描述,也无法将一个MD5的值变换回原始的字符串,从数学原理上说,是因为原始的字符串有无穷多个,这有点象不存在反函数的数学函数。)
在 Java 中,java.security.MessageDigest 中已经定义了 MD5 的计算,所以我们只需要简单地调用即可得到 MD5 的128 位整数。然后将此 128 位(即16 个字节)转换成 16 进制表示即可。

Java已经实现了MD5、SHA1算法。利用java.security.MessageDigest类就可以获取字符串和文件的MD5以及SHA1结果下面是一个工具类,可以获取字符串和文件进行MD5值。

import java.io.FileInputStream;
import java.security.DigestInputStream;
import java.security.MessageDigest;
/**
 * MD5工具类,获取字符串或者文件的MD5值
 * @author ouyangpeng
 * @link http://blog.csdn.net/ouyang_peng
 */
public class MD5Utils {
	/**
	 * 通过MD5加密字符串
	 * @param HASH_ALGORITHM
	 *                  加密算法,可以是MD5,SHA1
	 * @param input
	 *                  字符串
	 * @return 已经通过MD5算法加密的32位字符串
	 */
	public final static String stringToMD5(String input) {
		try {
			// 拿到一个MD5转换器,如果想要SHA1参数换成”SHA1”)
			MessageDigest messageDigest = MessageDigest.getInstance("MD5");
			// 输入的字符串转换成字节数组
			byte[] inputByteArray = input.getBytes();
			// inputByteArray是输入字符串转换得到的字节数组
			messageDigest.update(inputByteArray);
			// 转换并返回结果,也是字节数组,包含16个元素
			byte[] resultByteArray = messageDigest.digest();// MD5 的计算结果是一个 128 位的长度整数,
			// 字符数组转换成字符串返回
			return byteArrayToHex(resultByteArray);
		} catch (Exception e) {
			e.printStackTrace();
		}

		return null;
	}

	/**
	 * 通过MD5加密文件
	 * @param inputFile 文件路径
	 * @return 已经通过MD5算法加密的32位字符串
	 */
	public final static String fileToMD5(String inputFile) {
		int bufferSize = 256 * 1024;// 定义缓冲区大小
		FileInputStream fileInputStream = null;
		DigestInputStream digestInputStream = null;
		try {
			MessageDigest messageDigest = MessageDigest.getInstance("MD5");
			fileInputStream = new FileInputStream(inputFile);
			digestInputStream = new DigestInputStream(fileInputStream, messageDigest);
			byte[] buffer = new byte[bufferSize];
			while (digestInputStream.read(buffer) > 0)
				;
			messageDigest = digestInputStream.getMessageDigest();
			byte[] resultByteArray = messageDigest.digest();
			return byteArrayToHex(resultByteArray);
		} catch (Exception e) {
		} finally {
			try {
				digestInputStream.close();
			} catch (Exception e2) {
			}
		}
		return null;
	}

	/**
	 * @param byteArray
	 *                  byte数组
	 * @return 转后后的32位的字符串
	 */
	private static String byteArrayToHex(byte[] byteArray) {
		// 首先初始化一个字符数组,用来存放每个16进制字符
		char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };

		// new一个字符数组,这个就是用来组成结果字符串的(解释一下:一个byte是八位二进制,也就是2位十六进制字符(2的8次方等于16的2次方))
		char[] resultCharArray = new char[byteArray.length * 2];// 每个字节用 16 进制表示的话,使用两个字符

		// 遍历字节数组,通过位运算(位运算效率高),转换成字符放到字符数组中去
		int index = 0;
		// 从第一个字节开始,对MD5的每一个字节转换成16进制字符的转换
		for (byte b : byteArray) {
			// 取字节中高 4 位的数字转换
			//>>> 为逻辑右移(即无符号右移),将符号位一起右移
			resultCharArray[index++] = hexDigits[b >>> 4 & 0xf];
			// 取字节中低4位的数字转换
			resultCharArray[index++] = hexDigits[b & 0xf];
		}
		// 字符数组组合成字符串返回
		return new String(resultCharArray);
	}
}

下面是一个测试类,用于测试上面的MD5工具类是否有用

class MD5Test{
	public static void main(String[] args) {
		System.out.println(MD5Utils.stringToMD5("OuyangPeng"));
		long startTime = System.currentTimeMillis();
		System.out.println(MD5Utils.fileToMD5("/home/ouyangpeng/Android/CanplayComp/Code.tar.gz"));//9.6G的文件
		long endTime = System.currentTimeMillis();
		System.out.println("Time:" + (endTime - startTime) / 1000);
	}
}

测试结果如下:

30A81CB758C6918C7E43513839002171
05924A988C096A50B9BD4FA2AD7FA733
Time:86

参考链接:

  1. http://blog.csdn.net/xiao__gui/article/details/8148203
  2. http://baike.baidu.co/link?url=1IssoIidKtoOPvWnNHn4HaKsjYy7s4q85qO7uwrhxWA0mXxoiY3-84mss_wdGWpi

====================================================================================

  作者:欧阳鹏  欢迎转载,与人分享是进步的源泉!

  转载请保留原文地址:http://blog.csdn.net/ouyang_peng

===================================================================================

时间: 2024-08-03 08:51:17

我的Java开发学习之旅------>工具类:Java获取字符串和文件进行MD5值的相关文章

我的Java开发学习之旅------>Java经典面试题

摘自张孝祥itcast 从享受生活的角度上来说:"程序员并不是一种最好的职业,我认为两种人可以做程序员,第一,你不做程序员,你就没有什么工作可做,或者说是即使有可以做的工作但是你非常不愿意去做:第二,你非常痴迷和爱好程序,并且在这方面有一些天赋和优势.程序员的结局也是有两种:第一,默默退休,第二以程序员为起点或跳板,注意积累,跟对了好的老板或团队,找到和很好的搭档自己创业,成为IT金领和富翁." 人们在时间面前是平等的,吾生也有涯,所以,你的经验更丰富点,那不算什么,经验是用时间积累的

我的Java开发学习之旅------>Java字符编码解析

Java开发中,常常会遇到乱码的问题,一旦遇到这种问题,常常就很扯蛋,每个人都不愿意承认是自己的代码有问题.其实编码问题并没有那么神秘,那么不可捉摸,搞清Java的编码本质过程就真相大白了.               其实,编码问题存在两个方面:JVM之内和JVM之外.   1.Java文件编译后形成class 这里Java文件的编码可能有多种多样,但Java编译器会自动将这些编码按照Java文件的编码格式正确读取后产生class文件,这里的class文件编码是Unicode编码(具体说是UT

我的Java开发学习之旅------>Java ClassLoader解析一(转)

jvm classLoader architecture: Bootstrap ClassLoader/启动类加载器  主要负责jdk_home/lib目录下的核心 api 或 -Xbootclasspath 选项指定的jar包装入工作. Extension ClassLoader/扩展类加载器  主要负责jdk_home/lib/ext目录下的jar包或 -Djava.ext.dirs 指定目录下的jar包装入工作. System ClassLoader/系统类加载器  主要负责java -c

我的Java开发学习之旅------>Java ClassLoader解析二(转)

一.什么是ClassLoader?          大家都知道,当我们写好一个Java程序之后,不是管是CS还是BS应用,都是由若干个.class文件组织而成的一个完整的Java应用程序,当程序在运行时,即会调用该程序的一个入口函数来调用系统的相关功能,而这些功能都被封装在不同的class文件当中,所以经常要从这个class文件中要调用另外一个class文件中的方法,如果另外一个文件不存在的,则会引发系统异常.而程序在启动的时候,并不会一次性加载程序所要用的所有class文件,而是根据程序的需

我的Java开发学习之旅------>交通灯管理系统

1.交通灯管理系统的项目需求 模拟实现十字路口的交通灯管理系统逻辑,具体需求如下: Ø         异步随机生成按照各个路线行驶的车辆. 例如: 由南向而来去往北向的车辆 ---- 直行车辆        由西向而来去往南向的车辆 ---- 右转车辆        由东向而来去往南向的车辆 ---- 左转车辆        ... Ø         信号灯忽略黄灯,只考虑红灯和绿灯. Ø         应考虑左转车辆控制信号灯,右转车辆不受信号灯控制. Ø         具体信号灯控制

我的Java开发学习之旅------>JAVA IO 设计模式彻底分析

本文转载于网络. 一.引子(概括地介绍Java的IO) 无论是哪种编程语言,输入跟输出都是重要的一部分,Java也不例外,而且Java将输入/输出的功能和使用范畴做了很大的扩充.它采用了流的 机制来实现输入/输出,所谓流,就是数据的有序排列,而流可以是从某个源(称为流源或Source of Stream)出来,到某个目的地(称为流汇或Sink of Stream)去的.由流的方向,可以分成输入流和输出流,一个程序从输入流读取数据向输出流写数据. 如,一个程序可以用FileInputStream类

我的Java开发学习之旅------>Java资源的国际化详解

internationalization (国际化)简称 i18n,因为在i和n之间还有18个字符,localization(本地化 ),简称L10n. 国际化相关的Java类 Java国际化主要通过如下3个类完成 java.util.ResourceBundle:用于加载一个资源包 java.util.Locale:对应一个特定的国家/区域.语言环境. java.text.MessageFormat:用于将消息格式化 国际化资源文件 为实现程序的国际化,必须提供程序所需要的资源文件.资源文件的

我的Java开发学习之旅------>JAVA 笔记ClassLoader.getResourceAsStream() 与 Class.getResourceAsStream()的区别

今天,一读者在我的 Android通过调用Webservice实现手机号码归属地查询 文章中给我回复了一个问题,由于没有具体说明我的sop12.xml文件是放在src目录下,不是和具体操作类AddressService.java放在同一目录下,引起了误会. InputStream inputStream = AddressService.class.getClassLoader()                   .getResourceAsStream("sop12.xml");

我的Java开发学习之旅------>在Dos环境下Java内部类的编译和运行

习惯了在IDE工具上进行代码编写,连最基本的Javac命令和Java命令都忘记的差不多了,今天对一个Java内部类进行编译和运行的时候,就出糗了.IDE是把双刃剑,它可以什么都帮你做了,你只要敲几行代码,点几下鼠标,程序就跑起来了,用起来相当方便.你不用去关心它后面做了些什么,执行了哪些命令,基于什么原理.然而也是这种过分的依赖往往让人散失了最基本的技能,当到了一个没有IDE的地方,你便觉得无从下手,给你个代码都不知道怎么去跑. 首先我在C盘上编写了一个InnerClassTest.java代码