C语⾔实现Base64编码转码
关于Base64的介绍有两篇⽂章已经做得⾮常好了:⼀篇是,如果被Q可以看本⽂ ;另⼀篇是阮⼀峰的.
说⼀说C语⾔的实现吧,其实给出了C语⾔的实现了,但是它⽤以处理File,当然原理都是⼀样的,File的处理其实可以放在外⾯做好.
另外,根据Base64介绍可以看出来它以6⽐特为⼀个单元,⽽常规1字节为8⽐特,所以Base64编码的核⼼其实是位操作的过程.
好了,可以放代码了:
static const char *ALPHA_BASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
char *encode(const char *buf, const long size, char *base64Char) {
int a = 0;
int i = 0;
while (i < size) {
char b0 = buf[i++];
char b1 = (i < size) ? buf[i++] : 0;
char b2 = (i < size) ? buf[i++] : 0;
int int63 = 0x3F; // 00111111
int int255 = 0xFF; // 11111111
base64Char[a++] = ALPHA_BASE[(b0 >> 2) & int63];
base64Char[a++] = ALPHA_BASE[((b0 << 4) | ((b1 & int255) >> 4)) & int63];
base64Char[a++] = ALPHA_BASE[((b1 << 2) | ((b2 & int255) >> 6)) & int63];
base64Char[a++] = ALPHA_BASE[b2 & int63];
}
switch (size % 3) {
case 1:
base64Char[--a] = '=';
case 2:
base64Char[--a] = '=';
}
return base64Char;
}
char *decode(const char *base64Char, const long base64CharSize, char *originChar, long originCharSize) {
int toInt[128] = {-1};
for (int i = 0; i < 64; i++) {
toInt[ALPHA_BASE[i]] = i;
}
在线url网址编码解码int int255 = 0xFF;
int index = 0;
for (int i = 0; i < base64CharSize; i += 4) {
int c0 = toInt[base64Char[i]];
int c1 = toInt[base64Char[i + 1]];
originChar[index++] = (((c0 << 2) | (c1 >> 4)) & int255);
if (index >= originCharSize) {
return originChar;
}
int c2 = toInt[base64Char[i + 2]];
originChar[index++] = (((c1 << 4) | (c2 >> 2)) & int255);
if (index >= originCharSize) {
return originChar;
}
int c3 = toInt[base64Char[i + 3]];
originChar[index++] = (((c2 << 6) | c3) & int255);
}
return originChar;
}
在调⽤的时候⼀定要注意malloc的⼤⼩.
这个Base64其实我们经常在⽤,只是没有留意⽽已.⽐如P2P下载⼯具*雷就⽤Base64编码了很多资源,我这⾥了⼀个电影<;独⽴⽇:卷⼟重来.BD1280⾼清国英双语特效中英双字
>下载链接是这样
的: thu*der://QUFlZDJrOi8vfGZpbGV8JUU3JThCJUFDJUU3JUFCJThCJUU2JTk3JUE1JUVGJUJDJTlBJUU1JThEJUI3JUU1JTlDJTlGJUU5JTg3JThEJUU2JTlEJUE1LkJEMTI4MCVFOSVBQiU5OC 似挺聪明的做法,⾃定义了协议头,后⾯⼀⼤串晕晕乎乎的不知道是什么东西,⼀般的资源都是带⽂件名⾄少能看到后缀名啥的,不过看到最后⼜两个 '=' 字符,这个就很明显是这边⽂
章的主题Base64,在看这⾥⾯的字符都在Base64定义的字符内就可以认定这个是Base64编码后的链接.如果你恰好没装*雷,也不想装*雷(这货会偷偷上传⽂件,别问我怎么知道的,
亲⼿抓到的),就可以把协议头后⾯的⼀⼤串字符串拷贝出来,decode⼀下可以得
到 AAed2k://|file|%E7%8B%AC%E7%AB%8B%E6%97%A5%EF%BC%9A%E5%8D%B7%E5%9C%9F%E9%87%8D%E6%9D%A5.BD1280%E9%AB%98%E6%B8%85%E5%9B%BD%E8%8B%B1掉 AA 剩
下 ed2k://|file|%E7%8B%AC%E7%AB%8B%E6%97%A5%EF%BC%9A%E5%8D%B7%E5%9C%9F
%E9%87%8D%E6%9D%A5.BD1280%E9%AB%98%E6%B8%85%E5%9B%BD%E8%8B%B1%E 下认得了吧.⽤想⽤的下载⼯具下载吧.当然也可以⽤在线的base64 转码⼯具.
以下内容摘⾃
Base64是⼀种基于64个可打印字符来表⽰⼆进制数据的表⽰⽅法。由于2的6次⽅等于64,所以每6个为⼀个单元,对应某个可打印字符。三个有24个⽐特,对应于4个Base64单
元,即3个字节需要⽤4个可打印字符来表⽰。它可⽤来作为电⼦邮件的传输编码。在Base64中的可打印字符包括字母A-Z、a-z、数字0-9,这样共有62个字符,此外两个可打印
符号在不同的系统中⽽不同。⼀些如的其他编码⽅法,和之后的版本使⽤不同的64字符集来代表6个⼆进制数字,但是它们不叫Base64。
Base64常⽤于在通常处理⽂本数据的场合,表⽰、传输、存储⼀些⼆进制数据。包括MIME的email、在XML中存储复杂数据。
⽬录
[]
MIME[]
在格式的电⼦邮件中,base64可以⽤来将binary的字节序列数据编码成字符序列构成的⽂本。使⽤时,在传输编码⽅式中指定base64。使⽤的字符包括⼤⼩写字母各26个,加上
10个数字,和加号“+”,斜杠“/”,⼀共64个字符,等号“=”⽤来作为后缀⽤途。
完整的base64定义可见RFC 1421和RFC 2045。编码后的数据⽐原始数据略长,为原来的4
3。在电⼦邮件中,根据RFC 822规定,每76个字符,还需要加上⼀个回车换⾏。可以
估算编码后数据长度⼤约为原长的135.1%。
转换的时候,将三个byte的数据,先后放⼊⼀个24bit的缓冲区中,先来的byte占⾼位。数据不⾜3byte的话,于缓冲器中剩下的⽤0补⾜。然后,每次取出6(因为26=64)个bit,按照其值选择ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/中的字符作为编码后的输出。不断进⾏,直到全部输⼊数据转换完成。
当原数据长度不是3的整数倍时, 如果最后剩下⼀个输⼊数据,在编码结果后加2个“=”;如果最后剩下两个输⼊数据,编码结果后加1个“=”;如果没有剩下任何数据,就什么都不要加,这样才可以保证数据还原的正确性。
编码“Man”
⽂本M a n
ASCII编码7797110
⼆进制位010011010110000101101110
索引1922546
Base64编码T W F u
在此例中,Base64算法将三个字符编码为4个字符
Base64索引表:
数值字符数值字符数值字符数值字符
0A16Q32g48w
1B17R33h49x
2C18S34i50y
3D19T35j51z
4E20U36k520
5F21V37l531
6G22W38m542
7H23X39n553
8I24Y40o564
9J25Z41p575
10K26a42q586
11L27b43r597
12M28c44s608
13N29d45t619
14O30e46u62+
15P31f47v63/
如果要编码的字节数不能被3整除,最后会多出1个或2个字节,那么可以使⽤下⾯的⽅法进⾏处理:先使⽤0字节值在末尾补⾜,使其能够被3整除,然后再进⾏base64的编码。在编码后的base64⽂本后加上⼀个或两个'='号,代表补⾜的字节数。也就是说,当最后剩余⼀个⼋位字节(⼀个byte)时,最后⼀个6位的base64字节块有四位是0值,最后附加上两个等号;如果最后剩余两个⼋位字节(2个byte)时,最后⼀个6位的base字节块有两位是0值,最后附加⼀个等号。参考下表:
⽂本(1 Byte)A
⼆进制位01000001
⼆进制位(补0)010*********
Base64编码Q Q
⽂本(2 Byte)B C
⼆进制位0100001001000011x x x x x x
⼆进制位(补0)010000100100001100x x x x x x
Base64编码Q k M
UTF-7[]
是⼀个修改的Base64(Modified Base64)。主要是将的数据,⽤Base64的⽅法编码为可打印的字符序列。⽬的是传输Unicode数据。主要的区别在于不⽤等号"="补余,因为该字符通常需要⼤量的转译。
标准可见RFC 2152,《A Mail-Safe Transformation Format of Unicode》。
IRCu[]
在等软件所使⽤的P10 IRC服务器间协议中,对客户与服务器的消息类型号(client/server numerics)和⼆进制IP地址采⽤了base64编码。消息类型号的长度固定为3字节,故可直接编码为4个字节⽽不需要加填充。对IP地址进⾏编码时,则需要在地址前添加⼀些0⽐特,使之可以编码为整数个字节。这⾥所⽤的符号集与前述MIME的也有所不同,将+/改成了[]。
在URL中的应⽤[]
Base64编码可⽤于在环境下传递较长的标识信息。例如,在系统中,就采⽤了Base64来将⼀个较长的唯⼀标识符(⼀般为128-bit的)编码为⼀个字符串,⽤作HTTP表单和HTTP GET 中的参数。在其他应⽤程序中,也常常需要把⼆进制数据编码为适合放在URL(包括隐藏表单域)中的形式。此时,采⽤Base64编码不仅⽐较简短,同时也具有不可读性,即所编码的数据不会被⼈⽤⾁眼所直接看到。
然⽽,标准的Base64并不适合直接放在URL⾥传输,因为URL编码器会把标准Base64中的“/”和“+”字符变为形如“%XX”的形式,⽽这些“%”号在存⼊数据库时还需要再进⾏转换,因为中已将“%”号⽤作通配符。
为解决此问题,可采⽤⼀种⽤于URL的改进Base64编码,它不在末尾填充'='号,并将标准Base64中的“+”和“/”分别改成了“-”和“_”,这样就免去了在URL编解码和数据库存储时所要作的转换,避免了编码信息长度在此过程中的增加,并统⼀了数据库、表单等处对象标识符的格式。
另有⼀种⽤于正则表达式的改进Base64变种,它将“+”和“/”改成了“!”和“-”,因为“+”,“*”以及前⾯在IRCu中⽤到的“[”和“]”在中都可能具有特殊含义。
此外还有⼀些变种,它们将“+/”改为“_-”或“._”(⽤作编程语⾔中的标识符名称)或“.-”(⽤于中的Nmtoken)甚⾄“_:”(⽤于XML中的Name)。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论