CC++编程:url编解码实现
编码
为什么需要编码
为什么要进⾏URL编码?通常如果⼀样东西需要编码,说明这样东西并不适合直接进⾏传输。
1、会引起歧义:例如 URL 参数字符串中使⽤ key=value 这样的键值对形式来传参,键值对之间以 & 符号分隔,如 ?
postid=5038412&t=1450591802326,服务器会根据参数串的 & 和 = 对参数进⾏解析,如果 value 字符串中包含了 = 或者 & ,如宝洁公司的简称为P&G,假设需要当做参数去传递,那么可能URL所带参数可能会是这样 ?name=P&G&t=1450591802326,因为参数中多了⼀个&势必会造成接收 URL 的服务器解析错误,因此必须将引起歧义的 & 和 = 符号进⾏转义, 也就是对其进⾏编码。
2、⾮法字符:⼜如,URL 的编码格式采⽤的是 ASCII 码,⽽不是 Unicode,这也就是说你不能在 URL 中包含任何⾮ ASCII 字符,例如中⽂。否则如果客户端浏览器和服务端浏览器⽀持的字符集不同的情况下,中⽂可能会造成问题。
哪些字符需要编码
字母数字字符 “a” 到 “z”、“A” 到 “Z” 和 “0” 到 “9” 保持不变。
特殊字符 “.”、"-"、"*" 和 "_"保持不变。
空格字符 " " 转换为⼀个加号 “+”。
所有其他字符都是不安全的,因此:
⾸先使⽤⼀些编码机制将它们转换为⼀个或多个字节。
然后每个字节⽤⼀个包含 3 个字符的字符串 "%xy"表⽰,其中 xy 为该字节的两位⼗六进制表⽰形式。
推荐的编码机制是 UTF-8。
编码⽬的
是将不安全的字符转换为安全字符[UTF-8]
⽐如: ⽐如:
/wiki/春节—》/wiki/%E6%98%A5%E8%8A%82,也就是
说将"春节"编码成了"%E6%98%A5%E8%8A%82"。==》我们知道,“春"和"节"的utf-8编码分别是"E6 98 A5"和"E8 8A 82”,因
此,"%E6%98%A5%E8%8A%82"就是按照顺序,在每个字节前加上%⽽得到的
怎么编码
将需要转码的字符转为16进制,然后从右到左,取4位(不⾜4位直接处理),每2位做⼀位,前⾯加上%,编码成%XY格式。
static unsigned char enc_tab[]="0123456789ABCDEF";
int main(int argc,char* argv[])
{
const char*str ="中国⼈";
int len =strlen(str);
for(int i =0; i < len; i++){
printf("%d, %c, %c\n",(unsigned char)str[i],
在线url网址编码解码enc_tab[(unsigned char)str[i]>>4],// 取前4个
enc_tab[(unsigned char)str[i]&0x0F]// 取后4个
);
}
}
完整代码
/**
* URL 编码函数
* @param str {const char*} 源字符串
* @return {char*} 编码后的字符串,返回值不可能为空,需要⽤ free 释放
*/
static unsigned char enc_tab[]="0123456789ABCDEF";
char*acl_url_encode(const char*str){
int len =(int)strlen(str);
int tmp_len = len;
unsigned char*tmp =(unsigned char*)malloc(len +1);
int i, j;
for(i =0, j =0; i < len; i++, j++){
tmp[j]=(unsigned char) str[i];
if(!isalnum(tmp[j])&&strchr("_-.", tmp[j])==NULL){// 所传的字符不是字母和数字时,也不是_-.
tmp_len +=3;
tmp =(unsigned char*)realloc(tmp, tmp_len);
tmp[j++]='%';
tmp[j++]= enc_tab[(unsigned char)str[i]>>4];//
tmp[j]= enc_tab[(unsigned char)str[i]&0x0F];
}
}
tmp[j]='\0';
return(char*) tmp;
}
使⽤
const char*str ="中国⼈";
char* rs =acl_url_encode(str);
printf("%s\n", rs);
free(rs);
解码
既然有编码,就⼀定有解码。解码是编码的逆过程,因此:
如果我们发现了⼀个’%'字符,那么接下来的两个字符就是⼗六进制字符代码。将⼗六进制代码转换为⼗进制很简单:第⼀个字符需要乘以16(<< 4)
⽽另⼀个字符我们只需从hextable变量中获取值
源码
static unsigned char dec_tab[256]={
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,0,0,0,0,0,
0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0,
0,10,11,12,13,14,15,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,10,11,12,13,14,15,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,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,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,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
};
/**
* URL 解码函数
* @param str {const char*} 经URL编码后的字符串
* @return {char*} 解码后的字符串,返回值不可能为空,需要⽤ free 释放 */
char*acl_url_decode(const char*str){
int len =(int)strlen(str);
char*tmp =(char*)malloc(len +1);
int i =0, pos =0;
for(i =0; i < len; i++){
if(str[i]!='%')
tmp[pos]= str[i];
else if(i +2>= len){/* check boundary */
tmp[pos++]='%';/* keep it */
if(++i >= len)
break;
tmp[pos]= str[i];
break;
}else if(isalnum(str[i +1])&&isalnum(str[i +2])){
tmp[pos]=(dec_tab[(unsigned char) str[i +1]]<<4)
+ dec_tab[(unsigned char) str[i +2]];
i +=2;
}else
tmp[pos]= str[i];
pos++;
}
tmp[pos]='\0';
return tmp;
}
测试
const char*str ="中国⼈";
char* en =acl_url_encode(str);
char*de =acl_url_decode(en);
printf("%s <===> %s", en, de);
free(de);
free(en);
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论