Base_64编码原理以及java实现


前言

      Base_64编码广泛的应用在电子邮件传输中,因为在早期的电子邮件传输协议中,只支持ASCII码字符,导致非ASCII码字符的传输成为一个问题。

一、Base_64编码

      先介绍一下它的特点:经过Base64编码后的数据会比原始数据略长,为原来长度的4/3倍。并且经过Base64编码后的字符串的字符数是4的整数倍。究其原因,容在下细细道来。
      所谓编码,就是通过某种方式对二进制数据进行变换所得到的结果。
      而Base64中的64,即2的6次方,表示所针对的有效二进制长度为6位。从0到63这64个十进制值,每一个都对应于一个编码后字符,这就是Base64的字符映射表。比如 0 对应字符 ‘A’,25 对应字符 ‘Z’,26 对应字符 ‘a’,51 对应字符 ‘z’,52 对应字符 ‘0’,61 对应字符 ‘9’,62 对应字符 ‘+’,63 对应字符 ‘/’,用字符 ‘=’ 进行补位。
      即,如果有一个6位二进制串 “000001”,它对应的十进制为 1 ,所以它对应的Base64编码后的结果为 ‘B’ 。能够看到编码后的字符都是可打印字符,分别为‘A’-‘Z’,‘a’-‘z’,‘0’-'9’和‘+’,‘/’,一共64个字符,用 ‘=’ 进行补位。这些编码后的字符都用ASCII来表示, ‘B’ 的ASCII编码为 “0100 0010” 。ok,即对于6位二进制 “000001”的Base编码转换结果为8位 “0100 0010”,所以输出字符长度是原来长度的4/3倍。
      因为base64编码总是将3个8位二进制码分为一组,转换为4个6位二进制码,如果哪一组(一般是最后一组)不够24位的话,就在转换结果补上 ‘=’ 字符。所以Base64编码后的字符长度为4的整数倍。


      编码规则:

1,将给定的字符串以字符为单位转换为对应的字符编码(常见的ASCII码,还包括 GBK,UTF-8等编码)
2,将获得的字符编码转换为二进制流
3,对获得的二进制流做分组转换操作,每3个8位二进制为一组,转换为每4个6位二进制为一组(不足6位时,低位补0)。即每组的二进制数据长度为24
4,对获得的4个6位二进制码补位,向它们添加2位高位0,组成4个8位二进制码
5,将获得的4个8位二进制码转换为十进制(0-63)
6,按照字符映射表转换为对应的字符。

二、示例

编码

      对字符 ‘A’ 进行Base64编码:

字符 ‘A’
ASCII码 65
二进制码 01000001
4-6二进制码 010000 010000
4-8二进制码 00010000 00010000
十进制码 16 16
字符表映射 Q Q
所得结果为“QQ==”,会在后面补上两个’='字符凑成4个字符。等同于对二进制码 01000001 00000000 00000000 进行Base64编码。
      如果对两个ASCII码字符进行编码的话,后面会填充一个 ‘=’ 字符,原理类似,不再赘述。如果是三个ASCII码字符的话,不需要填充 ‘=’ ,因为刚好24位。

解码

       解码的话逆推即可。

java程序实现

      1,采用bouncycastle来实现。在它的release页面下载bcprov-jdk15to18-168.jar包(https://www.bouncycastle.org/latest_releases.html),再将它导入工程,然后导入相关的类文件即可。

package base64;

import org.bouncycastle.util.encoders.Base64;

public abstract class Base64Coder_BC
{

	public final static String ENCODING="UTF-8";
	
	
	public static String encode(String data) throws Exception
	{
		byte[] b=Base64.encode(data.getBytes(ENCODING));
		return new String(b,ENCODING);
	}
	
	
	public static String decode(String data) throws Exception
	{
		byte[] b=Base64.decode(data.getBytes(ENCODING));
		return new String(b,ENCODING);
	}

}

      测试代码如下:

package base64;

public class test_BC
{

	public static void main(String[] args) throws Exception
	{
		// TODO Auto-generated method stub
		String inputStr="今天是个好日子!";
		System.out.println("原文:\t"+inputStr);
		
		String code=Base64Coder_BC.encode(inputStr);
		System.out.println("编码后:\t"+code);
		
		String outputStr=Base64Coder_BC.decode(code);
		System.out.println("解码后:\t"+outputStr);
		
	}

}

      输出:
原文: 今天是个好日子!
编码后: 5LuK5aSp5piv5Liq5aW95pel5a2Q77yB
解码后: 今天是个好日子!

      2,采用apache下的commons codec来实现。在https://downloads.apache.org/commons/codec/页面中下载二进制文件 ,并将commons-codec-1.15.jar导入工程,然后导入相关的类文件即可。代码如下:(可参考api文档使用)

package base64;

import org.apache.commons.codec.binary.Base64;

public class Base64Coder_apache
{

	public final static String ENCODING="UTF-8";
	
	
	public static String encode(String data) throws Exception
	{
		byte[] b=Base64.encodeBase64(data.getBytes(ENCODING));
		return new String(b,ENCODING);
	}
	//需要说明:encode_rfc是采用RFC2045标准,每76个字符添加一个\r\n,若一行不够76个字符也需要添加。
	public static String encode_rfc(String data) throws Exception
	{
		byte[] b=Base64.encodeBase64(data.getBytes(ENCODING),true);
		return new String(b,ENCODING);
	}
		//解码时,不关心是否采用rfc标准定义的实现。
	public static String decode(String data) throws Exception
	{
		byte[] b=Base64.decodeBase64(data.getBytes(ENCODING));
		return new String(b,ENCODING);
	}
}

      测试代码:

package base64;

public class test
{

	public static void main(String[] args) throws Exception
	{
		// TODO Auto-generated method stub
		String inputStr="今天是个好日子!";
		System.out.println("原文:\t"+inputStr);
		
		String code=Base64Coder_apache.encode(inputStr);
		System.out.println("编码后:\t"+code);
		
		code=Base64Coder_apache.encode_rfc(inputStr);
		System.out.println("编码(rfc)后:\t"+code);
		
		String outputStr=Base64Coder_apache.decode(code);
		System.out.println("解码后:\t"+outputStr);
		
	}

}

      输出(注意回车换行符的效果):
原文: 今天是个好日子!
编码后: 5LuK5aSp5piv5Liq5aW95pel5a2Q77yB
编码(rfc)后: 5LuK5aSp5piv5Liq5aW95pel5a2Q77yB

解码后: 今天是个好日子!


总结

      总之,Base64编码不算复杂。但是在实现上,能够看出commons codec更加的具有优势,因为它还提供了RFC 2045标准定义的实现。如果提前约定好base64编码的字符映射表之后,它可以作为一个简单的加密解密算法来使用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值