您的位置:首页 > 编程语言 > Java开发

说说base64位编码。

2016-08-11 09:39 337 查看
   虽然网络上已经有许多的关于base64编码的介绍,但是自己还是想总结一点,为了以后防止自己忘记。先给大家看一串代码,出去就不明说了,这是一串利用base64对字符串进行编码的java代码。

public class BASE64Encoder
{
private static final char LAST2BYTE = (char) Integer.parseInt("00000011", 2);
private static final char LAST4BYTE = (char) Integer.parseInt("00001111", 2);
private static final char LAST6BYTE = (char) Integer.parseInt("00111111", 2);
private static final char LEAD6BYTE = (char) Integer.parseInt("11111100", 2);
private static final char LEAD4BYTE = (char) Integer.parseInt("11110000", 2);
private static final char LEAD2BYTE = (char) Integer.parseInt("11000000", 2);
private static final char[] ENCODE_TABLE = new char[] { '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', '+', '/' };
private static final String DEFAULT_ENCODING = "UTF-8";  //指定编码集
public BASE64Encoder()
{
}
public static String encode(String data)
throws UnsupportedEncodingException
{
return encode(data.getBytes(DEFAULT_ENCODING));
}
public static String encode(byte[] from)
{
StringBuffer to = new StringBuffer((int) (from.length * 1.34) + 3);
int num = 0;
char currentByte = 0;
for (int i = 0; i < from.length; i++)
{
num = num % 8;
while (num < 8)
{
switch (num)
{
case 0:
currentByte = (char) (from[i] & LEAD6BYTE);
currentByte = (char) (currentByte >>> 2);
break;
case 2:
currentByte = (char) (from[i] & LAST6BYTE);
break;
case 4:
currentByte = (char) (from[i] & LAST4BYTE);
currentByte = (char) (currentByte << 2);
if ((i + 1) < from.length)
{
currentByte |= (from[i + 1] & LEAD2BYTE) >>> 6;
}
break;
case 6:
currentByte = (char) (from[i] & LAST2BYTE);
currentByte = (char) (currentByte << 4);
if ((i + 1) < from.length)
{
currentByte |= (from[i + 1] & LEAD4BYTE) >>> 4;
}
break;
}
to.append(ENCODE_TABLE[currentByte]);
num += 6;
}
}
if (to.length() % 4 != 0)
{
for (int i = 4 - to.length() % 4; i > 0; i--)
{
to.append("=");
}
}
return to.toString();
}

}

  base64是一种基于64个可打印字符来表示二进制数据的表示方法,由于2的6次方等于64,所以每6个比特为一个单元,对应某个可打印字符。然后在6位前面补2个0形成一个8位的字节形式。例如我现在有一个24位的字节。它是3*8=24的形式,然后我们要把它分成4*6=24的形式。

eg: 11010101 11000101 00110011 (3*8=24)

00110101 00011100 00010100 00110011(4*6=24)

就是按顺序先拿出左边的6个位:110101 然后在最前面补2个0,形成00110101 这样就是第一个字节了。

然后接着取剩下的6位01 1100 ,前面补2个0变成00011100。

最后按顺序再去6位:010100 ,前面补2个0变成00010100.

同理最后剩下的6位:110011,前面补2个0变成00110011.

接下来我们来进行base64编码。先将所有的二进制转换成10进制,在从我们的encode_table里面找对应的数。其实encode——table里面的数就是字母A-Z、a-z、数字0-9,这样共有62个字符,此外的两个可打印符号在不同的系统中而不同,一般为+和/。注意47
v还有一个说法 47 pad = 
只是需要找到他们对应的序号。附上encdode_table表:



举个例子如何找:
例如有一个2进制数:00110101 编码后变成什么呢?(假装这个数是已经从8位变成6位在加了0的)
先对它进行二进制转十进制,应该会转吧。2^5+2^4+2^2+2^0=53,然后找到对应表中的数字就是53对应是1.base64编码得到的结果为1。
接下来都介绍了,就来整体的练习一个。
字符串“张3"进行base64编码得到是什么呢?
这里涉及到中文转二进制的操作。提供一个方法将字符串转为二进制的,我提供的是Java代码

String str = "张3";
byte[] b = str.getBytes();
for(int i=0;i<b.length;i++){
System.out.println(Integer.toBinaryString(b[i]&0xff));
}


然后得到11010101 11000101 00110011 (3*8)
    00110101 00011100 00010100 00110011(4*6)
都转换为十进制为 53  28   20  51
对照表所以转换后得到的base64编码为:1cUz   好啦,就这样转完了。
不过还得说一个问题。要是你的数凑不成6的倍数呢。

eg:11010101 11000101(2*8=16)


00110101 00011100 00010100(按照我们这样话分,前面补2个0,最后一个数也会只有6个,这样就在最后补0,缺几个补几个0,凑足8位就行)化成十进制:53
 28    20 pad (只有末尾补了0的记得就要写上pad)
这样base64编码就是:1cU=  (因为pad对应的是等于)。
--后续:后来我在前端里也遇见了需要用签名的地方,是用的名为cryptojs 的库,里面提供了多种javascript编写的算法,很方便。
说一说后续使用的用ts编写的一段用于计算签名的算法:(上面提到过,之前使用的是关于crypto的库,直接用库里面的方法计算就行);
getData(data, app_secret) {
let myData = [];
for (let x in data) {
let temp = `${x}=${data[x]}`;
myData.push(temp);
}
let result = myData.sort().join('&');
let b = new window['Base64']();
let sign = window['CryptoJS'].MD5(window['CryptoJS'].HmacSHA1(b.encode(result), app_secret)).toString();
return sign;
}
欢迎指教,如果有不对的,记得告诉我。
Thanks

 
    
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息