1、Base64是什么
Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法。Base64一般用于在 HTTP协议下传输二进制数据,由于 HTTP协议是文本协议,所以在 HTTP协议下传输二进制数据需要将二进制数据转换为字符数据。然而直接转换是不行的。因为网络传输只能传输可打印字符。 什么是可打印字符?在ASCII码中规定,0-31、127这33个字符属于控制字符,32~126这95个字符属于可打印字符,也就是说网络传输只能传输这95个字符,不在这个范围内的字符无法传输。那么该怎么才能传输其他字符呢?其中一种方式就是使用Base64。
2、Base64的编码规则
BASE64字符表:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
Base64编码的思想是是采用64个基本的ASCII码字符对数据进行重新编码。它将需要编码的数据拆分成字节数组。以3个字节为一组。按顺序排列24 位数据,再把这24位数据分成4组,即每组6位。再在每组的的最高位前补两个0凑足一个字节。这样就把一个3字节为一组的数据重新编码成了4个字节。当所要编码的数据的字节数不是3的整倍数,也就是说在分组时最后一组不够3个字节。这时在最后一组填充1到2个0字节。并在最后编码完成后在结尾添加1到2个 “=”。
例:将对ABC进行BASE64编码:
1、首先取ABC对应的ASCII码值。A(65)B(66)C(67);
2、再取二进制值A(01000001)B(01000010)C(01000011);
3、然后把这三个字节的二进制码接起来(010000010100001001000011);
4、 再以6位为单位分成4个数据块,并在最高位填充两个0后形成4个字节的编码后的值,(00010000)(00010100)(00001001)(00000011),其中蓝色部分为真实数据;
5、再把这四个字节数据转化成10进制数得(16)(20)(9)(3);
6、最后根据BASE64给出的64个基本字符表,查出对应的ASCII码字符(Q)(U)(J)(D),这里的值实际就是数据在字符表中的索引。
3、解码规则
解码过程就是把4个字节再还原成3个字节再根据不同的数据形式把字节数组重新整理成数据。
4、C#代码实现
static string base64encode_tbl = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static byte[] base64decode_tbl =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,62, 0, 0, 0,63,
52,53,54,55,56,57,58,59,60,61, 0, 0, 0, 0, 0, 0,
0, 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, 0, 0, 0, 0, 0,
0,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
};
public static string base64_encode(byte[] data)
{
StringBuilder sb = new StringBuilder();
byte[] cTemp = { 0, 0, 0 };
int len = data.Length;
int iDiv3Num = len / 3;
int iMod3Num = len % 3;
int line_len = 0;
int idx = 0;
for (int i = 0; i < iDiv3Num; i++)
{
cTemp[0] = data[idx++];
cTemp[1] = data[idx++];
cTemp[2] = data[idx++];
sb.Append(base64encode_tbl[cTemp[0] >> 2]);
sb.Append(base64encode_tbl[((cTemp[0] << 4) | (cTemp[1] >> 4)) & 0x3F]);
sb.Append(base64encode_tbl[((cTemp[1] << 2) | (cTemp[2] >> 6)) & 0x3F]);
sb.Append(base64encode_tbl[cTemp[2] & 0x3F]);
line_len += 4;
if (line_len == 76)
{
sb.Append("\r\n");
line_len = 0;
}
}
if (iMod3Num == 1)
{
cTemp[0] = data[idx++];
sb.Append(base64encode_tbl[(cTemp[0] & 0xFC) >> 2]);
sb.Append(base64encode_tbl[(cTemp[0] & 0x03) << 4]);
sb.Append("==");
}
else if (iMod3Num == 2)
{
cTemp[0] = data[idx++];
cTemp[1] = data[idx++];
sb.Append(base64encode_tbl[(cTemp[0] & 0xFC) >> 2]);
sb.Append(base64encode_tbl[((cTemp[0] & 0x03) << 4) | ((cTemp[1] & 0xF0) >> 4)]);
sb.Append(base64encode_tbl[((cTemp[1] & 0x0F) << 2)]);
sb.Append("=");
}
return sb.ToString();
}
public static byte[] base64_decode(string d_in)
{
byte[] data = System.Text.Encoding.UTF8.GetBytes(d_in);
int len = data.Length;
MemoryStream ms = new MemoryStream();
BinaryWriter bw = new BinaryWriter(ms);
int nValue;
int i = 0;
int idx = 0;
while (i < len)
{
if (data[idx] == '\r' || data[idx] == '\n')
{
idx++;
i++;
continue;
}
nValue = (int)(base64decode_tbl[data[idx++]] << 18);
nValue += (int)(base64decode_tbl[data[idx++]] << 12);
int c3 = (nValue & 0x00FF0000) >> 16;
bw.Write((byte)c3);
if (data[idx] != '=')
{
nValue += (int)(base64decode_tbl[data[idx++]] << 6);
int c4 = (nValue & 0x0000FF00) >> 8;
bw.Write((byte)c4);
if (data[idx] != '=')
{
nValue += (int)(base64decode_tbl[data[idx++]]);
int c5 = nValue & 0x000000FF;
bw.Write((byte)c5);
}
}
i += 4;
}
return ms.ToArray();
}