之前想给简陋的webserver加一个小功能。在html界面上输入文字,然后发送给服务器,服务器接收再发送回去(回射服务器)。
然后发现中文的接收过来是一堆 %+16进制数,开始以为在html里设置什么就能解决,后来查了半天也找不到什么方法,发现是编码方式的问题, 然后找了一堆关于读取utf-8文本的解答,发现好像都不太行,于是尝试自己解码试试。
思路: 将字节流存在string中,查找%及其之后的数,对于多字节的utf-8编码的,判断出字节数,然后进行转换
string decoder_u8(const string& origin) //origin为utf-8字符
{
string res(origin);
int l=1, r=origin. Size()-2;
//去掉%
l=0,r=0;
while(r<res.size())
{
if(res[r]=='%') r++;
else res[l++] = res[r++];
}
res.resize(origin.size()-origin.size()/3);
//字符转ASCII 全是大写
for(int i=0;i<res.size();++i)
{
if(res[i]<='9'&&res[i]>='0') res[i] -= '0';
else res[i] = res[i]-'A'+10;
}
//两两各取出后4位组成数
for(int i=0;i<res.size()/2;++i)
{
res[i] = res[2*i]<<4 | res[2*i+1]; //TODO: 为什么+不可用
}
res.resize(res.size()/2);
return res;
}
string decoder(const string& origin)
{
int i=0;
string s = "";
while(i<origin.size())
{
if(origin[i]!='%') s.append(origin.substr(i++,1));
else
{
char tmp = origin[i+1];
if(tmp<='9'&&tmp>='0') tmp -= '0';
else tmp = tmp-'A'+10;
if(tmp == 15) // 4字节
{
s.append( decoder_u8(origin.substr(i,12)) );
i+=12;
}
else if(tmp>>1 == 7) // 3字节
{
s.append( decoder_u8(origin.substr(i,9)) );
i+=9;
}
else if(tmp>>2 == 3) // 2字节
{
s.append( decoder_u8(origin.substr(i,6)) );
i+=6;
}
else if(tmp>>1 == 1) // 1字节
{
s.append( decoder_u8(origin.substr(i,3)) );
i+=3;
}
else
{
cout<<"接收字符串编码错误!"<<endl;
return "接收字符串编码错误!";
}
}
}
return s;
}
test
string o("%E5%B0%91");
cout<<decoder(o)<<endl;
output : 少
如果有什么简便的方法,欢迎交流