`

java模拟实现base64算法的编码过程

阅读更多

如题,base算法 包括编码、解码两部分本次实现的是编码的过程,
其中没用使用位运算,所有位运算都是通过字符串的拼接完成 ,代码如下:

其中log4j部分可以替换成 Syste.out.println();

 

package org.jshand.base64;

import org.apache.log4j.Logger;

import sun.misc.BASE64Encoder;

/**
 * 【Base64】
 *	-base64的编码都是按字符串长度,以每3个8bit的字符为一组,
 *	-然后针对每组,首先获取每个字符的ASCII编码,
 *	-然后将ASCII编码转换成8bit的二进制,得到一组3*8=24bit的字节
 *	-然后再将这24bit划分为4个6bit的字节,并在每个6bit的字节前面都填两个高位0,得到4个8bit的字节
 *	-然后将这4个8bit的字节转换成10进制,对照Base64编码表 (下表),得到对应编码后的字符。
 *	 
 *	(注:1. 要求被编码字符是8bit的,所以须在ASCII编码范围内,\u0000-\u00ff,中文就不行。
 *	   2. 如果被编码字符长度不是3的倍数的时候,则都用0代替,对应的输出字符为=)
 *
 *				T           o           m
	ASCII:      84          111         109
	bit字节:   01010100    01101111    01101101
	bit字节:     010101      000110      111101      101101
	十进制:     21          6           61          45
	对应编码:   V           G           9           t
	
	
				L           u           c           y
	ASCII:      76          117         99          121
	bit字节:   01001100    01110101    01100011    01111001      00000000    00000000
	bit字节:   010011      000111      010101      100011      	011110  	010000  000000  000000
	十进制:     19          7           21          35             30      	16      (异常) (异常)      
	对应编码:    T           H           V           j              e       	Q       =       =
	
				d
	ASCII:      100
	8bit字节:   01100100  	00000000 	00000000
	6bit字节:   00011001 	00000000 	00000000	00000000
	十进制:                 
	对应编码:     
	
 *
 * @file_name	Base64Impl.java
 * @project		base64
 * @author  	jshand
 * @createDate	Jun 18, 2013  3:00:46 PM
 * @version 	1.0
 * http://www.jshand.com
 * 
 */

public class Base64Impl {
	static Logger logger = Logger.getLogger(Base64Impl.class);
	
	
	public static char[] ascii = {
		'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 
        'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 
        'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 
        'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 
        'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 
        'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', 
        '8', '9', '+', '/'
	};
	
 
	
	/**
	 * 讲原始字符串拆分成 固定长度,每三个字符为一组字符串数组
	 * 数组的最后一个可能元素可能长度小于三
	 * 
	 * @example 
	 * 1 原始字符串 "abcdefgh" 拆分后的字符串数组为 {"abc","eef","gh"};
	 * @param String src
	 * @return
	 */
	
	public static String[] GETCOMB(String src){
		logger.debug("************************将字符串分成 每三个字符一组 开始************************");
		StringBuilder sb = new StringBuilder(src);
		int strLength = sb.length();
		int combLeng =0;
		if(strLength%3 == 0){
			combLeng = strLength/3;
		}else{
			combLeng = (strLength/3)+1;
		}
		logger.debug("组合长度 -->"+combLeng);
		String[] comb= new String [combLeng];
		int index = 0;
		while(sb.length()>0){
			String subString = "";
			if( sb.length()>3 ){
				subString = sb.substring(0, 3);
				sb.replace(0, 3, "");
			}else{
				subString = sb.substring(0, sb.length());
				sb.replace(0, sb.length(), "");
			}
			logger.debug("GETCOMB\t\t"+index+" --subString--> "+subString);
			comb[index] = subString;
			index++;
		}
		logger.debug("************************将字符串分成 每三个字符一组 结束************************\n\n");
		return comb;
	}
	
	/**
	 * 每三个字符 转换成ASCII码并 得到 24bit的字节  
	 * 需要一个combs 字符串数组,数组中的每个元素为一个字符串,
	 * 每个字符串的长度范围 在 1-3个 之间 包含1和3 
	 * @param combs
	 * @return
	 */
	public static String[] STRINGTOBINARY(String combs[]){
		String binaryCombs[] = new String[combs.length];
		logger.debug("************************每三个字符 转换成ASCII码并 得到 24bit的字节 开始************************");
		StringBuffer sb = null;
		StringBuffer singleChar = null;
		for (int i = 0; i < combs.length; i++) {
			sb = new StringBuffer();
			logger.debug("----------------------------------");
			String appendStr = "" ;
			char[] cs=combs[i].toCharArray();
			for (int j = 0; j < cs.length; j++) {
				singleChar = new StringBuffer();
				logger.debug("转换之前的二进制内容 -->"+Integer.toBinaryString((int)cs[j]));
				singleChar.append(Integer.toBinaryString((int)cs[j]));
				switch (singleChar.length()) {
				case 1:
					appendStr = "0000000"+singleChar.toString();
					break;
				case 2:
					appendStr = "000000"+singleChar.toString();
					break;
				case 3:
					appendStr = "00000"+singleChar.toString();
					break;
				case 4:
					appendStr = "0000"+singleChar.toString();
					break;
				case 5:
					appendStr = "000"+singleChar.toString();
					break;
				case 6:
					appendStr = "00"+singleChar.toString();
					break;
				case 7:
					appendStr = "0"+singleChar.toString();
					break;
				default:
					break;
				}
				logger.debug("转换之后的二进制内容 -->"+appendStr);
				sb.append(appendStr);
			}
			binaryCombs[i] = sb.toString();
			logger.debug("\t\tSTRINGTOBINARY 组("+i+") 二进制内容-->"+sb.toString());
			
		}
		logger.debug("************************每三个字符 转换成ASCII码并 得到 24bit的字节 结束************************\n\n");
		return binaryCombs;
	}
	
	public static String BINARYTOBINARY(String combs[]) throws Exception{
		logger.debug("************************将这24bit划分为4个6bit的字节,并在每个6bit的字节前面都填两个高位0,得到4个8bit的字节 开始************************");
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < combs.length; i++) {
			String comb = combs[i];
			logger.debug("\t\tcomb["+i+"].length = "+comb.length()+"\tcombs["+i+"]-->"+comb);
			switch (comb.length()) {
			case 8:
				sb.append(ascii[Integer.parseInt(	comb.substring(0,6)		,2	)]);
				sb.append(ascii[Integer.parseInt(	comb.substring(6)+"0000",2)]);
				sb.append("=");
				sb.append("=");
				break;
			case 16:
				sb.append(ascii[Integer.parseInt(	comb.substring(0,6)		,2	)]);
				sb.append(ascii[Integer.parseInt(	comb.substring(6,12)		,2	)]);
				sb.append(ascii[Integer.parseInt(	comb.substring(12)+"00",2)]);
				sb.append("=");
				break;
			case 24:
				sb.append(ascii[Integer.parseInt(	comb.substring(0,6)		,2	)]);
				sb.append(ascii[Integer.parseInt(	comb.substring(6,12)	,2	)]);
				sb.append(ascii[Integer.parseInt(	comb.substring(12,18)	,2	)]);
				sb.append(ascii[Integer.parseInt(	comb.substring(18)		,2	)]);
				break;
			default:
				throw new Exception("转换异常,不是正常的二进制数组");
			}
		}
		logger.debug("************************将这24bit划分为4个6bit的字节,并在每个6bit的字节前面都填两个高位0,得到4个8bit的字节 结束************************\n\n");
		return sb.toString();
		
	}
	
	
	public static void main(String[] args) throws Exception {
		
//		String str = "abcdefghafafjafajflajfal;fkjhttp://1201201012012012012102102102198048jalfjalsfjas;lfjas;lfkjsa;lkfjsa;lfkjsalfkjsaf";
//		String str = "a";
//		String str = "b";
//		String str = "c";
//		String str = "d";
		String str = "abcdef";
		//1 将字符串分解成3个字符的字符串数组"abcdef" =={"abc","def"}
		String strs[] = GETCOMB(str);
		//2 将字符串数组的内容 每个字符转换成{"abc","def"} = {"011000010110001001100011","011001000110010101100110"}
		String binaryCombs[] = STRINGTOBINARY(strs);
		//3 将 3个8bit 拆分成4个6bit 并在高位高位补两个零, 每个6bit转换成10进制,通过10进制去ASCII码表中比较去除字符
		String mybase = BINARYTOBINARY(binaryCombs);
		
		
		
		//***************测试打印 的字符串*****************************
		System.err.println("1."+mybase);
		
		//通过与sun.misc包下类BASE64Encoder的encode方法比较  ,结果一致
		BASE64Encoder encoder = new BASE64Encoder();
		System.err.println("2."+encoder.encode(str.getBytes()));

	}
	
}

 
参考资料 :
http://ascii.911cha.com/ (关于base64编码的原理及实现 )
http://www.cnblogs.com/hongru/archive/2012/01/14/2321397.html(ASCII码对照表)

0
5
分享到:
评论

相关推荐

    PowerBuilder+Base-64加密

    1. **使用内置函数**:虽然PowerBuilder的标准库中没有直接的Base-64编码函数,但我们可以利用字符串操作函数模拟实现。例如,可以将二进制数据分割成6位块,然后将每个6位块转换为十进制,查找其在Base-64字符集中...

    Java编码摘要算法实例解析

    总的来说,Java提供了丰富的API来支持编码摘要算法,包括URL编码、Base64编码、MD5和SHA1等哈希函数。这些工具在保证数据安全、防止篡改、验证文件完整性等方面起着关键作用。通过实例学习和实践,开发者可以更好地...

    NDK开发的Demo

    在Android的NDK环境中,由于Java标准库不适用于原生代码,所以通常需要使用第三方库,如OpenSSL或自定义的Base64实现。Base64编码将任意二进制数据转换成ASCII字符序列,使得数据可以在不支持二进制的环境(如电子...

    Java模拟新浪微博登陆抓取数据

    【Java模拟新浪微博登陆抓取数据】的实现涉及多个关键技术点,包括HTTP请求、JSON解析、RSA加密和Base64编码。以下是对这些知识点的详细解释: 1. **HTTP请求**: - **GET请求**:在预登录阶段,Java通过GET方法...

    commons.zip

    Apache Commons Codec提供了高效的Base64编码和解码实现,支持URL安全和MIME格式。 2. **Hex编码和解码**:Hex编码将每个字节转换为两个十六进制数字,方便在文本环境中显示二进制数据。这个库提供了便捷的Hex编码...

    用Java写的一个QQ聊天程序

    7. **消息编码与解码**:可能需要了解Base64、JSON等编码方式,以便于在网络间传输文本和结构化数据。 8. **安全通信**:考虑使用SSL/TLS协议加密通信,防止数据被窃取,保护用户隐私。 9. **异常处理**:在编程...

    30个常用java工具类

    19. **`java.util.Base64`**:Base64编码和解码,用于数据传输和存储。 20. **`java.nio`** 包:非阻塞I/O,提高效率,特别是在服务器端编程中。 21. **`java.util.zip`** 包:处理压缩和解压缩,如...

    android手机动态口令模拟

    在Android中,可以使用开源库如`zappernode`的`java-hotp`来实现HOTP算法。 在Android手机上模拟动态口令,我们需要以下几个步骤: 1. **密钥生成**: 用户设置动态口令时,服务器会生成一个密钥(通常为16到32...

    commons-codec-1.14_java_modbus_ashapproxany_

    这个库是Java编程语言中的一个开源项目,提供了一系列编码和解码算法,包括Base64、Hex、URL编码、Phonetic编码、以及一些其他特定格式的编码。在Modbus协议的数据采集应用中,这类编码库可能会用于处理或转换数据,...

    网页手写签名生成图片

    开发这样一个系统,通常会设计一套RESTful API接口,比如一个POST接口接收轨迹数据,返回生成的签名图片URL或Base64编码的图像数据。前端通过Ajax调用这个接口,实现签名的动态生成和保存。 7. **前端用户体验**:...

    java后端请求HTTP需要用到的jar包及其测试方法(get和post)

    5. **commons-codec-1.10.jar**:Apache Commons Codec库包含各种编码和解码算法,如Base64、URL编码等,常用于HTTP请求中的数据编码。 6. **commons-lang-2.5.jar**:Apache Commons Lang提供了一些Java语言功能的...

    手写签名,可以保存图片,并页面显示TestDemo.

    在JavaScript中,可以使用HTML5的`canvas.toDataURL()`方法来获取画布的内容作为Base64编码的图像数据,然后进一步保存为文件。 在页面显示方面,一旦签名被保存为图像,应用可以将该图像加载到页面上的某个元素,...

    JAVA 进制转换 参考代码

    然而,对于自定义进制如62进制的转换,Java标准库没有直接提供支持,我们需要自己实现算法。这个过程通常分为两步:首先,将原始值转换为特定基数(如16进制),然后将这个基数的值转换为目标基数(如62进制)。 在...

    Jmeter 二次开发 函数助手 AES加解密

    在这个项目中,开发者可能使用了Java的javax.crypto包来实现AES加解密,该包提供了实现各种加密算法的类和接口。通过自定义JMeter插件,可以将这些功能无缝地集成到测试脚本中,使得测试人员无需深入理解加密原理,...

    PCM转G711A/G711U代码

    2. `g711codec.cpp` 应该包含了实际的G711编码和解码算法实现,可能包含两个函数,分别负责将PCM数据转换为G711A或G711U,以及将G711A或G711U数据还原为PCM。 对应的头文件 `IOVoices.h` 和 `g711codec.h` 可能定义...

    commons-codec.jar;commons-logging-1.1.jar;commons-httpclient-3.1.jar

    Apache Commons Codec库提供了各种编码和解码算法的实现,如Base64、Hex、URL编码和解码等。它使得开发者能够轻松地在Java项目中使用这些编码格式,而无需自己实现。例如,Base64编码常用于在网络上传输二进制数据,...

    算法 常見程式演算 程式練習題目

    10. **编码与解码**:如Base64编码、哈希函数等,它们在数据传输和存储中起着重要作用。 通过练习这些题目,不仅可以提升你的编程技巧,还能使你在面对实际工作中的复杂问题时更有信心。同时,使用C和Java这两种...

    baidu-master.zip

    1. **上传图片**:将验证码图片转换为适合网络传输的格式,如Base64编码,然后将其作为请求的参数。 2. **发送请求**:构造API调用的URL,添加必要的认证信息和请求参数,发送HTTP请求。 3. **接收响应**:处理...

Global site tag (gtag.js) - Google Analytics