base64编码的java实现
虽然有现成的库,自己也写了个,顺便学习一下忘记了很久的东西。
编码过程:参考wiki
引用
将三个byte的数据,先后放入一个24bit的缓冲区中,先来的byte占高位。数据不足3byte的话,于缓冲区中剩下的bit用0补足。然后,每次取出6(因为26 = 64)个bit,按照其值选择ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/中的字符作为编码后的输出。不断进行,直到全部输入数据转换完成。
如果最后剩下两个输入数据,在编码结果后加1个“=”;如果最后剩下一个输入数据,编码结果后加2个“=”;如果没有剩下任何数据,就什么都不要加,这样才可以保证资料还原的正确性。
下面开始实现:
首先需要实现2个函数,一个是将整数转化为二进制串,一个是将二进制串转化为整数。
整数转化为二进制串,书上说用辗转相除法,一直除2知道为1为止,让后讲模2的余数反过来即得。
参照jdk Integer类里的toBinaryString方法实现。可以通过移位和遮罩实现,此方法比辗转相处简短的多了。。
这是代码:
/**
* 一个字节转化为8位二进制数列数组,数组的低序号表示二进制数列的高位,不足8位,高位补0
*/
public static byte[] byteTo8BinaryBytes(byte t){
byte[] res = new byte[8];
/**移位**/
int mask = 1;
int shift = 1;
int pos = 8;
do{
res[--pos] = (byte) (t & mask);
t >>>= shift;
}while(pos != 0);//总共才8位
/**通过辗转除2**/
/*
if(t == 0)return res;
int i=0;
do{
res[i++] = (byte) (t%2);
t = (byte) (t/2);
if(t == 1){
res[i++] = (byte) t;
break;
}
}while(true);
//将res反过来
for(i=0; i< 4;i++){
byte b = res[i];
res[i] = res[7-i];
res[7-i] = b;
} */
return res;
}
二进制转10进制则。一个个相乘即可:
/**
* 二进制字节数组转化为十进制整数,数组的低序号表示二进制数列的高位
*/
public static int binaryBytesArrToInt(byte[] bytes){
int res = 0;
int size = bytes.length;
int pow2 = 1;
for(int i= size-1; i>=0;i--){
byte b = bytes[i];
if(b == 1){
res += pow2;
}
pow2 = pow2 << 1;
}
return res;
}
下面开始base64编码,每3个byte处理,转化为二进制数组,放到一个24byte的数组里,然后每6个读取出来到一个8byte数组,下标从2开始
将这个byte数组再转化为byte,然后作为索引读取char值。。最后如果是0的数组要加=,最多加2个==。加了几个0就加几个=。比如只有一个字母d
要转化必须加2个byte 0的字节才够3个,因此转化结果最后2个字节为=
/**
* base64编码
*
*/
public static String encryptBase64(byte[] bytes){
byte[] buffer = new byte[24];
StringBuffer sb = new StringBuffer();
for(int i=0;i<bytes.length ;i+=3){
byte b1,b2,b3;
b1 = bytes[i];
if(i + 1 <bytes.length){
b2 = bytes[i+1];
}else{
b2 = 0;
}
if(i + 2 <bytes.length){
b3 = bytes[i+2];
}else{
b3 = 0;
}
byte[] tbs = byteTo8BinaryBytes(b1);
System.arraycopy(tbs, 0, buffer, 0, 8);
tbs = byteTo8BinaryBytes(b2);
System.arraycopy(tbs, 0, buffer, 8, 8);
tbs = byteTo8BinaryBytes(b3);
System.arraycopy(tbs, 0, buffer, 16, 8);
//每次取6个
int idx = 0;
do{
byte[] bt = new byte[8];
System.arraycopy(buffer, idx, bt, 2, 6);
byte btb = (byte) binaryBytesArrToInt(bt);
if(btb != 0){
sb.append(index[btb]);
}else{
if(idx == 6){//最多只能有2个=
sb.append(index[btb]);
}else{
sb.append('=');
}
}
idx += 6;
if(idx >= 24)break;
}while(true);
}
return sb.toString();
}
解码过程正好相反,每4个byte组合成一个24位的buffer,再组合成3字节的byte。直到最后,如果最后2个有一个为=。则跳出不用再转换了
/**
* base64解码
*/
public static byte[] decryptbase64(byte[] bytes){
//每4个byte组合成一个24位的buffer,再组合成3字节的byte。直到最后,如果最后2个有一个为=。则跳出不用再转换了
List<Byte> list = new ArrayList<Byte>();
for(int i=0; i<bytes.length ;i+=4){
byte c1 = bytes[i];
byte c2 = bytes[i+1];
byte c3 = bytes[i+2];
byte c4 = bytes[i+3];
c1 = getByteIndex(c1);
c2 = getByteIndex(c2);
c3 = getByteIndex(c3);
c4 = getByteIndex(c4);
byte[] buffer = new byte[24];
byte[] tbts = byteTo8BinaryBytes(c1);
System.arraycopy(tbts, 2, buffer, 0, 6);
tbts = byteTo8BinaryBytes(c2);
System.arraycopy(tbts, 2, buffer, 0+6, 6);
tbts = byteTo8BinaryBytes(c3);
System.arraycopy(tbts, 2, buffer, 0+12, 6);
tbts = byteTo8BinaryBytes(c4);
System.arraycopy(tbts, 2, buffer, 0+18, 6);
tbts = new byte[8];
byte temp;
System.arraycopy(buffer, 0, tbts, 0, 8);
temp = (byte) binaryBytesArrToInt(tbts);
list.add(temp);
if(bytes[i+2] == '=')break;
System.arraycopy(buffer, 8, tbts, 0, 8);
temp = (byte) binaryBytesArrToInt(tbts);
list.add(temp);
if(bytes[i+3] == '=')break;
System.arraycopy(buffer, 16, tbts, 0, 8);
temp = (byte) binaryBytesArrToInt(tbts);
list.add(temp);
}
byte[] res = new byte[list.size()];
int i=0;
for(Byte B:list){
res[i++] = B.byteValue();
}
return res;
}
其他的数据:主要是base64索引和值查询
private static byte getByteIndex(byte b){
if(b >= 'A' && b<= 'Z'){
return (byte) (b - 'A');
}
if(b >= 'a' && b<= 'z'){
return (byte) (b - 'a' + 26);
}
if(b >= '0' && b<= '9'){
return (byte) (b - '0' + 52);
}
if(b == '+')return 62;
if(b == '/')return 63;
return 0;
}
private static final char[] index = 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','+','/'
};
这是测试数据和输出结果:
String str = "helloworld";
log(str);
String str0 = encryptBase64(str.getBytes());
log(str0);
String str1 = new String(decryptbase64(str0.getBytes()));
log(str1);
helloworld
aGVsbG93b3JsZA==
helloworld