C#实现Base64编码与解码及编码名称和代码页(Encoding.GetEncoding)
2011-09-15 10:29 elivsit 阅读(1306) 评论(0) 编辑 收藏 举报一、编码规则
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),这里的值实际就是数据在字符表中的索引。
注:BASE64字符表:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
二、解码规则
解码过程就是把4个字节再还原成3个字节再根据不同的数据形式把字节数组重新整理成数据。
三、C#中的实现
编码类:
/// <summary>
/// Base64编码类。
/// 将byte[]类型转换成Base64编码的string类型。
/// </summary>
public class Base64Encoder
{
byte[] source;
int length, length2;
int blockCount;
int paddingCount;
public static Base64Encoder Encoder = new Base64Encoder();
public Base64Encoder()
{
}
private void init(byte[] input)
{
source = input;
length = input.Length;
if ((length % 3) == 0)
{
paddingCount = 0;
blockCount = length / 3;
}
else
{
paddingCount = 3 - (length % 3);
blockCount = (length + paddingCount) / 3;
}
length2 = length + paddingCount;
}
public string GetEncoded(byte[] input)
{
//初始化
init(input);
byte[] source2;
source2 = new byte[length2];
for (int x = 0; x < length2; x++)
{
if (x < length)
{
source2[x] = source[x];
}
else
{
source2[x] = 0;
}
}
byte b1, b2, b3;
byte temp, temp1, temp2, temp3, temp4;
byte[] buffer = new byte[blockCount * 4];
char[] result = new char[blockCount * 4];
for (int x = 0; x < blockCount; x++)
{
b1 = source2[x * 3];
b2 = source2[x * 3 + 1];
b3 = source2[x * 3 + 2];
temp1 = (byte)((b1 & 252) >> 2);
temp = (byte)((b1 & 3) << 4);
temp2 = (byte)((b2 & 240) >> 4);
temp2 += temp;
temp = (byte)((b2 & 15) << 2);
temp3 = (byte)((b3 & 192) >> 6);
temp3 += temp;
temp4 = (byte)(b3 & 63);
buffer[x * 4] = temp1;
buffer[x * 4 + 1] = temp2;
buffer[x * 4 + 2] = temp3;
buffer[x * 4 + 3] = temp4;
}
for (int x = 0; x < blockCount * 4; x++)
{
result[x] = sixbit2char(buffer[x]);
}
switch (paddingCount)
{
case 0: break;
case 1: result[blockCount * 4 - 1] = '='; break;
case 2: result[blockCount * 4 - 1] = '=';
result[blockCount * 4 - 2] = '=';
break;
default: break;
}
return new string(result);
}
private char sixbit2char(byte b)
{
char[] lookupTable = new char[64]{
'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','+','/'};
if ((b >= 0) && (b <= 63))
{
return lookupTable[(int)b];
}
else
{
return ' ';
}
}
}
解码类:
/// <summary>
/// Base64解码类
/// 将Base64编码的string类型转换成byte[]类型
/// </summary>
public class Base64Decoder
{
char[] source;
int length, length2, length3;
int blockCount;
int paddingCount;
public static Base64Decoder Decoder = new Base64Decoder();
public Base64Decoder()
{
}
private void init(char[] input)
{
int temp = 0;
source = input;
length = input.Length;
for (int x = 0; x < 2; x++)
{
if (input[length - x - 1] == '=')
temp++;
}
paddingCount = temp;
blockCount = length / 4;
length2 = blockCount * 3;
}
public byte[] GetDecoded(string strInput)
{
//初始化
init(strInput.ToCharArray());
byte[] buffer = new byte[length];
byte[] buffer2 = new byte[length2];
for (int x = 0; x < length; x++)
{
buffer[x] = char2sixbit(source[x]);
}
byte b, b1, b2, b3;
byte temp1, temp2, temp3, temp4;
for (int x = 0; x < blockCount; x++)
{
temp1 = buffer[x * 4];
temp2 = buffer[x * 4 + 1];
temp3 = buffer[x * 4 + 2];
temp4 = buffer[x * 4 + 3];
b = (byte)(temp1 << 2);
b1 = (byte)((temp2 & 48) >> 4);
b1 += b;
b = (byte)((temp2 & 15) << 4);
b2 = (byte)((temp3 & 60) >> 2);
b2 += b;
b = (byte)((temp3 & 3) << 6);
b3 = temp4;
b3 += b;
buffer2[x * 3] = b1;
buffer2[x * 3 + 1] = b2;
buffer2[x * 3 + 2] = b3;
}
length3 = length2 - paddingCount;
byte[] result = new byte[length3];
for (int x = 0; x < length3; x++)
{
result[x] = buffer2[x];
}
return result;
}
private byte char2sixbit(char c)
{
char[] lookupTable = new char[64]{
'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','+','/'};
if (c == '=')
return 0;
else
{
for (int x = 0; x < 64; x++)
{
if (lookupTable[x] == c)
return (byte)x;
}
return 0;
}
}
}
//解码类结束
提示:
上面的代码只是说明base64编码的原理,以便用更多语言重写。但.net里面可以使用更简单的方法:
编码:
byte[] bytes=Encoding.Default.GetBytes("要转换的字符串");
Convert.ToBase64String(bytes);
解码:
//"ztKwrsTj"是“我爱你”的base64编码
byte[] outputb = Convert.FromBase64String("ztKwrsTj");
string orgStr= Encoding.Default.GetString(outputb);
在.net开发中常用到Encoding.GetEncoding(int codeage)或者Encoding.GetEncoding(string name)来获取一个Encoding,通常大部分人是记不住这些codepage(代码页)和name(名称)的,本人也曾经有过这样的经历,现在整理出来供大家参考。
代码页(codepage) |
名称(name) |
显示名称 |
|
---|---|---|---|
37 |
IBM037 |
IBM EBCDIC(美国 - 加拿大) |
|
437 |
IBM437 |
OEM 美国 |
|
500 |
IBM500 |
IBM EBCDIC(国际) |
|
708 |
ASMO-708 |
阿拉伯字符 (ASMO 708) |
|
720 |
DOS-720 |
阿拉伯字符 (DOS) |
|
737 |
ibm737 |
希腊字符 (DOS) |
|
775 |
ibm775 |
波罗的海字符 (DOS) |
|
850 |
ibm850 |
西欧字符 (DOS) |
|
852 |
ibm852 |
中欧字符 (DOS) |
|
855 |
IBM855 |
OEM 西里尔语 |
|
857 |
ibm857 |
土耳其字符 (DOS) |
|
858 |
IBM00858 |
OEM 多语言拉丁语 I |
|
860 |
IBM860 |
葡萄牙语 (DOS) |
|
861 |
ibm861 |
冰岛语 (DOS) |
|
862 |
DOS-862 |
希伯来字符 (DOS) |
|
863 |
IBM863 |
加拿大法语 (DOS) |
|
864 |
IBM864 |
阿拉伯字符 (864) |
|
865 |
IBM865 |
北欧字符 (DOS) |
|
866 |
cp866 |
西里尔字符 (DOS) |
|
869 |
ibm869 |
现代希腊字符 (DOS) |
|
870 |
IBM870 |
IBM EBCDIC(多语言拉丁语 2) |
|
874 |
windows-874 |
泰语 (Windows) |
|
875 |
cp875 |
IBM EBCDIC(现代希腊语) |
|
932 |
shift_jis |
日语 (Shift-JIS) |
|
936 |
gb2312 |
简体中文 (GB2312) |
* |
949 |
ks_c_5601-1987 |
朝鲜语 |
|
950 |
big5 |
繁体中文 (Big5) |
|
1026 |
IBM1026 |
IBM EBCDIC(土耳其拉丁语 5) |
|
1047 |
IBM01047 |
IBM 拉丁语 1 |
|
1140 |
IBM01140 |
IBM EBCDIC(美国 - 加拿大 - 欧洲) |
|
1141 |
IBM01141 |
IBM EBCDIC(德国 - 欧洲) |
|
1142 |
IBM01142 |
IBM EBCDIC(丹麦 - 挪威 - 欧洲) |
|
1143 |
IBM01143 |
IBM EBCDIC(芬兰 - 瑞典 - 欧洲) |
|
1144 |
IBM01144 |
IBM EBCDIC(意大利 - 欧洲) |
|
1145 |
IBM01145 |
IBM EBCDIC(西班牙 - 欧洲) |
|
1146 |
IBM01146 |
IBM EBCDIC(英国 - 欧洲) |
|
1147 |
IBM01147 |
IBM EBCDIC(法国 - 欧洲) |
|
1148 |
IBM01148 |
IBM EBCDIC(国际 - 欧洲) |
|
1149 |
IBM01149 |
IBM EBCDIC(冰岛语 - 欧洲) |
|
1200 |
utf-16 |
Unicode |
* |
1201 |
UnicodeFFFE |
Unicode (Big-Endian) |
* |
1250 |
windows-1250 |
中欧字符 (Windows) |
|
1251 |
windows-1251 |
西里尔字符 (Windows) |
|
1252 |
Windows-1252 |
西欧字符 (Windows) |
* |
1253 |
windows-1253 |
希腊字符 (Windows) |
|
1254 |
windows-1254 |
土耳其字符 (Windows) |
|
1255 |
windows-1255 |
希伯来字符 (Windows) |
|
1256 |
windows-1256 |
阿拉伯字符 (Windows) |
|
1257 |
windows-1257 |
波罗的海字符 (Windows) |
|
1258 |
windows-1258 |
越南字符 (Windows) |
|
1361 |
Johab |
朝鲜语 (Johab) |
|
10000 |
macintosh |
西欧字符 (Mac) |
|
10001 |
x-mac-japanese |
日语 (Mac) |
|
10002 |
x-mac-chinesetrad |
繁体中文 (Mac) |
|
10003 |
x-mac-korean |
朝鲜语 (Mac) |
* |
10004 |
x-mac-arabic |
阿拉伯字符 (Mac) |
|
10005 |
x-mac-hebrew |
希伯来字符 (Mac) |
|
10006 |
x-mac-greek |
希腊字符 (Mac) |
|
10007 |
x-mac-cyrillic |
西里尔字符 (Mac) |
|
10008 |
x-mac-chinesesimp |
简体中文 (Mac) |
* |
10010 |
x-mac-romanian |
罗马尼亚语 (Mac) |
|
10017 |
x-mac-ukrainian |
乌克兰语 (Mac) |
|
10021 |
x-mac-thai |
泰语 (Mac) |
|
10029 |
x-mac-ce |
中欧字符 (Mac) |
|
10079 |
x-mac-icelandic |
冰岛语 (Mac) |
|
10081 |
x-mac-turkish |
土耳其字符 (Mac) |
|
10082 |
x-mac-croatian |
克罗地亚语 (Mac) |
|
20000 |
x-Chinese-CNS |
繁体中文 (CNS) |
|
20001 |
x-cp20001 |
TCA 台湾 |
|
20002 |
x-Chinese-Eten |
繁体中文 (Eten) |
|
20003 |
x-cp20003 |
IBM5550 台湾 |
|
20004 |
x-cp20004 |
TeleText 台湾 |
|
20005 |
x-cp20005 |
Wang 台湾 |
|
20105 |
x-IA5 |
西欧字符 (IA5) |
|
20106 |
x-IA5-German |
德语 (IA5) |
|
20107 |
x-IA5-Swedish |
瑞典语 (IA5) |
|
20108 |
x-IA5-Norwegian |
挪威语 (IA5) |
|
20127 |
us-ascii |
US-ASCII |
* |
20261 |
x-cp20261 |
T.61 |
|
20269 |
x-cp20269 |
ISO-6937 |
|
20273 |
IBM273 |
IBM EBCDIC(德国) |
|
20277 |
IBM277 |
IBM EBCDIC(丹麦 - 挪威) |
|
20278 |
IBM278 |
IBM EBCDIC(芬兰 - 瑞典) |
|
20280 |
IBM280 |
IBM EBCDIC(意大利) |
|
20284 |
IBM284 |
IBM EBCDIC(西班牙) |
|
20285 |
IBM285 |
IBM EBCDIC(英国) |
|
20290 |
IBM290 |
IBM EBCDIC(日语片假名) |
|
20297 |
IBM297 |
IBM EBCDIC(法国) |
|
20420 |
IBM420 |
IBM EBCDIC(阿拉伯语) |
|
20423 |
IBM423 |
IBM EBCDIC(希腊语) |
|
20424 |
IBM424 |
IBM EBCDIC(希伯来语) |
|
20833 |
x-EBCDIC-KoreanExtended |
IBM EBCDIC(朝鲜语扩展) |
|
20838 |
IBM-Thai |
IBM EBCDIC(泰语) |
|
20866 |
koi8-r |
西里尔字符 (KOI8-R) |
|
20871 |
IBM871 |
IBM EBCDIC(冰岛语) |
|
20880 |
IBM880 |
IBM EBCDIC(西里尔俄语) |
|
20905 |
IBM905 |
IBM EBCDIC(土耳其语) |
|
20924 |
IBM00924 |
IBM 拉丁语 1 |
|
20932 |
EUC-JP |
日语(JIS 0208-1990 和 0212-1990) |
|
20936 |
x-cp20936 |
简体中文 (GB2312-80) |
* |
20949 |
x-cp20949 |
朝鲜语 Wansung |
* |
21025 |
cp1025 |
IBM EBCDIC(西里尔塞尔维亚 - 保加利亚语) |
|
21866 |
koi8-u |
西里尔字符 (KOI8-U) |
|
28591 |
iso-8859-1 |
西欧字符 (ISO) |
* |
28592 |
iso-8859-2 |
中欧字符 (ISO) |
|
28593 |
iso-8859-3 |
拉丁语 3 (ISO) |
|
28594 |
iso-8859-4 |
波罗的海字符 (ISO) |
|
28595 |
iso-8859-5 |
西里尔字符 (ISO) |
|
28596 |
iso-8859-6 |
阿拉伯字符 (ISO) |
|
28597 |
iso-8859-7 |
希腊字符 (ISO) |
|
28598 |
iso-8859-8 |
希伯来字符 (ISO-Visual) |
* |
28599 |
iso-8859-9 |
土耳其字符 (ISO) |
|
28603 |
iso-8859-13 |
爱沙尼亚语 (ISO) |
|
28605 |
iso-8859-15 |
拉丁语 9 (ISO) |
|
29001 |
x-Europa |
欧罗巴 |
|
38598 |
iso-8859-8-i |
希伯来字符 (ISO-Logical) |
* |
50220 |
iso-2022-jp |
日语 (JIS) |
* |
50221 |
csISO2022JP |
日语(JIS- 允许 1 字节假名) |
* |
50222 |
iso-2022-jp |
日语(JIS- 允许 1 字节假名 - SO/SI) |
* |
50225 |
iso-2022-kr |
朝鲜语 (ISO) |
* |
50227 |
x-cp50227 |
简体中文 (ISO-2022) |
* |
51932 |
euc-jp |
日语 (EUC) |
* |
51936 |
EUC-CN |
简体中文 (EUC) |
* |
51949 |
euc-kr |
朝鲜语 (EUC) |
* |
52936 |
hz-gb-2312 |
简体中文 (HZ) |
* |
54936 |
GB18030 |
简体中文 (GB18030) |
* |
57002 |
x-iscii-de |
ISCII 梵文 |
* |
57003 |
x-iscii-be |
ISCII 孟加拉语 |
* |
57004 |
x-iscii-ta |
ISCII 泰米尔语 |
* |
57005 |
x-iscii-te |
ISCII 泰卢固语 |
* |
57006 |
x-iscii-as |
ISCII 阿萨姆语 |
* |
57007 |
x-iscii-or |
ISCII 奥里雅语 |
* |
57008 |
x-iscii-ka |
ISCII 卡纳达语 |
* |
57009 |
x-iscii-ma |
ISCII 马拉雅拉姆语 |
* |
57010 |
x-iscii-gu |
ISCII 古吉拉特语 |
* |
57011 |
x-iscii-pa |
ISCII 旁遮普语 |
* |
65000 |
utf-7 |
Unicode (UTF-7) |
* |
65001 |
utf-8 |
Unicode (UTF-8) |
* |
65005 |
utf-32 |
Unicode (UTF-32) |
* |
65006 |
utf-32BE |
Unicode (UTF-32 Big-Endian) |