【转】Base64算法详解

原文链接:https://blog.csdn.net/robertcpp/article/details/51628647

  完整的BASE64定义可见RFC 1421RFC 2045。编码后的数据比原始数据略长,为原来的4/3。在电子邮件中,根据RFC 822规定,每76个字符,还需要加上一个回车换行。可以估算编码后数据长度大约为原长的135.1%。

  转换的时候,将三个byte的数据,先后放入一个24bit的缓冲区中,先来的byte占高位。数据不足3byte的话,于缓冲器中剩下的bit用0补足。然后,每次取出6(因为26=64)个bit,按照其值选择ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/中的字符作为编码后的输出。不断进行,直到全部输入数据转换完成。

  当原数据长度不是3的整数倍时, 如果最后剩下一个输入数据(原始数据按3个一组,剩下一个),在编码结果后加2个“=”;如果最后剩下两个输入数据(原始数据按3个一组,剩下两个),编码结果后加1个“=”;如果没有剩下任何数据,就什么都不要加,这样才可以保证数据还原的正确性。

例子

举例来说,一段引用自托马斯·霍布斯利维坦》的文句:

Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.

经过Base64编码之后变成:

TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz
IHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2Yg
dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGlu
dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRo
ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=
  • 编码“Man”
文本Man
ASCII编码7797110
二进制位010011010110000101101110
索引1922546
Base64编码TWFu

在此例中,Base64算法将三个字符编码为4个字符

Base64索引表:

数值字符 数值字符 数值字符 数值字符
0A16Q32g48w
1B17R33h49x
2C18S34i50y
3D19T35j51z
4E20U36k520
5F21V37l531
6G22W38m542
7H23X39n553
8I24Y40o564
9J25Z41p575
10K26a42q586
11L27b43r597
12M28c44s608
13N29d45t619
14O30e46u62+
15P31f47v63/

  如果要编码的字节数不能被3整除,最后会多出1个或2个字节,那么可以使用下面的方法进行处理:先使用0字节值在末尾补足,使其能够被3整除,然后再进行Base64的编码。在编码后的Base64文本后加上一个或两个'='号,代表补足的字节数。也就是说,当最后剩余一个八位字节(一个byte)时,最后一个6位的Base64字节块有四位是0值,最后附加上两个等号;如果最后剩余两个八位字节(2个byte)时,最后一个6位的base字节块有两位是0值,最后附加一个等号。 参考下表:

文本(1 Byte)A  
二进制位01000001                
二进制位(补0)010000010000            
Base64编码QQ  
文本(2 Byte)BC 
二进制位0100001001000011  xxxxxx
二进制位(补0)010000100100001100xxxxxx
Base64编码QkM 

public
class Base64 { /** * 将原始数据编码为base64编码 */ static public char[] encode(byte[] data) { char[] out = new char[((data.length + 2) / 3) * 4]; for (int i = 0, index = 0; i < data.length; i += 3, index += 4) { boolean quad = false; boolean trip = false; int val = (0xFF & (int) data[i]); val <<= 8; if ((i + 1) < data.length) { val |= (0xFF & (int) data[i + 1]); trip = true; } val <<= 8; if ((i + 2) < data.length) { val |= (0xFF & (int) data[i + 2]); quad = true; } out[index + 3] = alphabet[(quad ? (val & 0x3F) : 64)]; val >>= 6; out[index + 2] = alphabet[(trip ? (val & 0x3F) : 64)]; val >>= 6; out[index + 1] = alphabet[val & 0x3F]; val >>= 6; out[index + 0] = alphabet[val & 0x3F]; } return out; } /** * 将base64编码的数据解码成原始数据 */ static public byte[] decode(char[] data) { int len = ((data.length + 3) / 4) * 3; if(data.length > 0 && data[data.length - 1] == '=') --len; if(data.length > 1 && data[data.length - 2] == '=') --len; byte[] out = new byte[len]; int shift = 0; int accum = 0; int index = 0; for(int ix = 0; ix < data.length; ix++) { int value = codes[data[ix] & 0xFF]; if(value >= 0) { accum <<= 6; shift += 6; accum |= value; if(shift >= 8) { shift -= 8; out[index++] = (byte)((accum >> shift) & 0xff); } } } if(index != out.length) throw new Error("miscalculated data length!"); return out; } static private char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".toCharArray(); static private byte[] codes = new byte[256]; static { for (int i = 0; i < 256; i++) codes[i] = -1; for (int i = 'A'; i <= 'Z'; i++) codes[i] = (byte) (i - 'A'); for (int i = 'a'; i <= 'z'; i++) codes[i] = (byte) (26 + i - 'a'); for (int i = '0'; i <= '9'; i++) codes[i] = (byte) (52 + i - '0'); codes['+'] = 62; codes['/'] = 63; } public static void main(String[] args) throws Exception { //加密成base64 String strSrc = "林"; String strOut = new String(Base64.encode(strSrc.getBytes())); System.out.println(strOut); String strOut2 = new String(Base64.decode(strOut.toCharArray())); System.out.println(strOut2); } }

 

转载于:https://www.cnblogs.com/xdouby/p/9009148.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值