哈希表和哈希函数和fileinputstream

1、哈希表

       经过记录的存储位置和它的关键字之间创建一个肯定的对应关系 f  以及处理冲突的方法,使得每一个关键字和结构中一个惟一的存储位置相对应。这样对于关键字 K  根据对应关系 f  ,就能够找到存储在 f(K) .称这种对应关系为 哈希函数,按照这种方法创建的表称为哈希表。html

1.1 原 理

       经过记录的存储位置和它的关键字之间创建一个肯定的对应关系,使得每一个关键字和结构中一个惟一的存储位置相对应。这样对于关键字 K  根据对应关系 f  ,就能够找到存储在 f(K) .称这种对应关系f 为 哈希函数,按照这种方法创建的表称为哈希表。java

1.2 冲 突

       对不一样的关键字可能获得同一个存储位置-哈希地址,即  key1  不等于 key2 ,可是 f(key1)=f(key2),这种现象称为冲突。
git

1.3 哈希表的构造方法

1.3.1 均匀哈希函数
算法

       任何一个关键字被映射到地址集合中任何一个地址的几率都是均等的。能够采用直接地址法。`f(K)=a.key+bapache

2、补充学习知识-fileinputstream

public class FileInputStreamextends InputStream

2.1 FileInputStream 类的主要做用。

FileInputStream obtains input bytes from a file in a file system. What files are available depends on the host environment.api

FileInputStream is meant for reading streams of raw bytes such as image data. For reading streams of characters, consider using FileReader.数组

2.2 read()方法

public int read(byte[] b)
         throws IOException

Reads up to b.length bytes of data from this input stream into an array of bytes. This method blocks until some input is available.ide

  • Overrides:函数

  • read in class InputStream学习

  • Parameters:

  • b - the buffer into which the data is read.

  • Returns:

    the total number of bytes read into the buffer, or -1 if there is no more data because the end of the file has been reached.

  • Throws:

  • IOException - if an I/O error occurs.

  • See Also:

  • InputStream.read(byte[], int, int)

3、实例测试-生成的byte数组要转换成16进制字符串输出

package com.yuan.test;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import org.apache.log4j.Logger;

public class MD5builder {

	static Logger logger = Logger.getLogger(MD5builder.class);
	// 用来将字节转换成 16 进制表示的字符
	static char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
			'9', 'a', 'b', 'c', 'd', 'e', 'f' };

	/**
	 * 对文件全文生成MD5摘要
	 * 
	 * @param file
	 *            要加密的文件
	 * @return MD5摘要码
	 */
	public static String getMD5(File file) {
		FileInputStream fis = null;
		try {
			MessageDigest md = MessageDigest.getInstance("MD5");

			logger.info("MD5摘要长度:" + md.getDigestLength());
			fis = new FileInputStream(file);// 读入文件
			byte[] buffer = new byte[2048];
			int length = -1;
			logger.info("开始生成摘要");
			long s = System.currentTimeMillis();
			while ((length = fis.read(buffer)) != -1) {
				md.update(buffer, 0, length);
				/****
				 * Parameters: input - the array of bytes. offset - the offset
				 * to start from in the array of bytes. len - the number of
				 * bytes to use, starting at offset.
				 * 
				 * 
				 */
			}
			logger.info("摘要生成成功,总用时: " + (System.currentTimeMillis() - s)
					+ "ms");
			byte[] b = md.digest();
			return byteToHexString(b);
			// 16位加密
			// return buf.toString().substring(8, 24);
		} catch (Exception ex) {
			logger.error(ex);
			ex.printStackTrace();
			return null;
		} finally {
			try {
				fis.close();
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}
	}

	/**
	 * 对一段String生成MD5加密信息
	 * 
	 * @param message
	 *            要加密的String
	 * @return 生成的MD5信息
	 */
	public static String getMD5(String message) {
		try {
			MessageDigest md = MessageDigest.getInstance("MD5");
			logger.info("MD5摘要长度:" + md.getDigestLength());
			byte[] b = md.digest(message.getBytes());
			return byteToHexString(b);
		} catch (NoSuchAlgorithmException e) {
			logger.error(e);
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 把byte[]数组转换成十六进制字符串表示形式
	 * 
	 * @param tmp
	 *            要转换的byte[]
	 * @return 十六进制字符串表示形式
	 */
	private static String byteToHexString(byte[] tmp) {
		String s;
		// 用字节表示就是 16 个字节
		char str[] = new char[16 * 2]; // 每一个字节用 16 进制表示的话,使用两个字符,
		// 因此表示成 16 进制须要 32 个字符
		int k = 0; // 表示转换结果中对应的字符位置
		for (int i = 0; i < 16; i++) { // 从第一个字节开始,对 MD5 的每个字节
			// 转换成 16 进制字符的转换
			byte byte0 = tmp[i]; // 取第 i 个字节
			str[k++] = hexDigits[byte0 >>> 4 & 0xf]; // 取字节中高 4 位的数字转换,
			// >>> 为逻辑右移,将符号位一块儿右移
			str[k++] = hexDigits[byte0 & 0xf]; // 取字节中低 4 位的数字转换
		}
		s = new String(str); // 换后的结果转换为字符串
		return s;
	}
}

4、MD5加密算法体会-参考博文

http://blog.csdn.net/magister_feng/article/details/8266540

MD5 (Message Digest  Algorithm 5 信息—摘要算法5 ) 的一些体会

4.1 举例说明

若咱们定义一个函数 ,原型为: 

String  MD5 ( Information info)

其中Information 表示任意长度的信息,注意是任意长度的。

实现这个函数的最终要求:

一、对于不一样的输入信息,产生的返回值 结果不一样 且必须惟一

二、该算法不可逆转,也就是就算拥有 返回结果和算法细节,也不可能推导出输入的初始信息。

下面是MD5算法对一些特定值产生的返回值:

  md5 ("") = d41d8cd98f00b204e9800998ecf8427e 
   md5 ("a") = 0cc175b9c0f1b6a831c399e269772661 
   md5 ("abc") = 900150983cd24fb0d6963f7d28e17f72 
   md5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0 
   md5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b 
      md5("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789")

=d174ab98d277d9f5a5611c2c9f419d9f                md5("12345678901234567890123456789012345678901234567890123456789012345678901234567890")  = 57edf4a22be3c955ac49da2e2107b67a 

     对于第二个要求,就是说,给你 一个 32位的字符串d41d8cd98f00b204e9800998ecf8427e,若是不事先告诉你,那你一生都别想得出它的输入信息是 一个空白字符。

4.二、一些典型的应用。

   1. 对一段信息(message)产生信息摘要(message-digest),以防止被篡改。好比,在unix下有不少软件在下载的时候都有一个文件名相同,文件扩展名为.md5的文件,在这个文件中一般只有一行文本,大体结构如:

   md5 (tanajiya.tar.gz) = 0ca175b9c0f726a831d895e269332461 
  这就是tanajiya.tar.gz文件的数字签名。md5将整个文件看成一个大文本信息,经过其不可逆的字符串变换算法,产生了这个惟一的md5信息摘要。若是在之后传播这个文件的过程当中,  不管文件的内容发生了任何形式的改变(包括人为修改或者下载过程当中线路不稳定引发的传输错误等),只要你对这个文件从新计算md5时就会发现信息摘要不相同,由此能够肯定你获得的只是一个不正确的文件。  

    2.防止抵赖。这须要有第三方权威机构的参与。A 写了个文件,权威机构对改文件用MD5算法产生摘要信息作好记录。若之后A说这文件不是我写的,权威机构只需对改文件从新产生摘要信息跟记录在册的摘要信息进行比对,相同的话,就证实是A写的了。这就是所谓的“数字签名”了。

   3. 加密信息。好比在unix系统中用户的密码就是以md5(或其它相似的算法)经加密后存储在文件系统中。当用户登陆的时候,系统把用户输入的密码计算成md5值,而后再去和保存在文件系统中的md5值进行比较,进而肯定输入的密码是否正确。经过这样的步骤,系统在并不知道用户密码的明码的状况下就能够肯定用户登陆系统的合法性。这不但能够避免用户的密码被具备系统管理员权限的用户知道,并且还在必定程度上增长了密码被破解的难度。

相关文章
相关标签/搜索