Base64编、解码原理,及代码实现(二)

//------------------------------------分割线--------------------------------------------//
解码代码:
string Base64Decode(const string &s)//s形参是编码后的字符串
{
int lenString = s.length();
string StrSource = s;
//表中的数值是表示在Base64表中的值,也就是6位2进制数的10进制的值!
const int dekey[]={
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
62, // '+'
-1, -1, -1,
63, // '-'
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // '0'-'9'
-1, -1, -1, -1, -1, -1, -1,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // 'A'-'Z'
-1, -1, -1, -1, -1, -1,
26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // 'a'-'z'
};




if(lenString % 4 != 0)
throw "Bad Base64 string";


int nLoop = (StrSource[lenString-1]=='=') ? lenString-4:lenString;
//不论传进来的形参最后有一个还是两个"=",都要少进行一个循环,所以以最后一个"="为准;


string DecodeStr(lenString*3/4+4,'\0');
int b[4]={0};
int i=0,n=0;
//cout<<dekey[static_cast<int>(StrSource[1])]<<endl;
for(i=0;i<nLoop;i+=4)
{
//其实,这里的StrSource[i]虽然是字符型,不过它通过隐性转换由char类型->int类型
//char类型->2进制->10进制int类型
b[0]=dekey[StrSource[i]];
b[1]=dekey[StrSource[i+1]];
b[2]=dekey[StrSource[i+2]];
b[3]=dekey[StrSource[i+3]];




if(b[0] == -1 || b[1] == -1 || b[2] == -1 || b[3] == -1)
             throw "bad base64 string";


DecodeStr[n]=((b[0] & 0x3f)<<2)|((b[1] & 0x30)>>4);
DecodeStr[n+1]=((b[1] & 0x0f)<<4)|((b[2] & 0x3c)>>2);
DecodeStr[n+2]=((b[2] & 0x03)<<6)|((b[3] &0x3f));


n+=3;
}


if(StrSource[lenString-1]=='=' && StrSource[lenString-2]=='=')
{
b[0]=dekey[StrSource[i]];
b[1]=dekey[StrSource[i+1]];




if(b[0] == -1 || b[1] == -1)
             throw "bad base64 string";




DecodeStr[n]=((b[0] & 0x3f)<<2)|((b[1]&0x30)>>4);
DecodeStr[n+1]='\0';
}
if(StrSource[lenString-1]=='=' && StrSource[lenString-2]!='=')
{
b[0]=dekey[StrSource[i]];
b[1]=dekey[StrSource[i+1]];
b[2]=dekey[StrSource[i+2]];




if(b[0] == -1 || b[1] == -1 || b[2]== -1)
             throw "bad base64 string";


DecodeStr[n]=((b[0] & 0x3f)<<2)|((b[1]&0x30)>>4);
DecodeStr[n+1]=((b[1]&0xf)<<4)|((b[2]&0x3c)>>2);
DecodeStr[n+2]='\0';
}
if( StrSource[lenString-1] != '=' && StrSource[lenString-2] != '=' )
         DecodeStr[n] = '\0';




//这里返回string类型的C风格字符串,这样可以将string类型变量多余的'\0'除去
return DecodeStr.c_str();
};

3.解码中的位运算(编码的位运算同理)

  其中对于6位2进制转8位2进制的过程,例如:DecodeStr[n]=((b[0] & 0x3f)<<2)|((b[1]&0x30)>>4)。由于b[0]是一个6位2进制数,比如是110011=51,变成8位2进制数的话是00110011,那么经过b[0] & 0x3f 得到6位的后6位,然后向左移位2,就变成了11001100,同理b[1]&0x30也是一样,比如b[1]=00100001=33,因为b[0]是6位有效,那么就要求b[1]的前2位要与b[0]的6位结合变成8位2进制数,过程如下:
  b[0] & 0x3 == 00110011,b[1] & 0x30 == 00100000,然后通过位运算,b[0]左移6位,b[1]右移4,再由或运算得到:11001100 | 00000010 = 11001110,这就是最后的8位2进制数,算出它的值然后使得char类型变量等于此2进制数,计算机通过查表,得到了该2进制数所对应的字符。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值