`

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
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics