URL中文问题

URL编码原理

网页URL的合法字符分成两类:

  • URL元字符:分号(;),逗号(,),斜杠(/),问号(?),冒号(:),at(@),&,等号(=),加号(+),美元符号($),井号(#)

  • 语义字符:a-z,A-Z,0-9,连词号(-),下划线(_),点(.),感叹号(!),波浪线(~),星号(*),单引号(),圆括号(())

除了以上字符,其他字符出现在URL之中都必须转义,规则是根据操作系统的默认编码,将每个字节转为百分号(%)加上两个大写的十六进制字母,这些不是什么乱码,而是UTF-8编码或者gbk(GB2312)编码,那些百分号(%)后面的数字和字母其实就是16进制数。

  • 如果是中文的gbk(GB2312)编码,那么它的形式应该是这样的,即一个汉字对应两组%xx,即%xx%xx

  • 如果是中文的UTF-8编码,那么它的形式应该是这样的,即一个汉字对应三组%xx,即%xx%xx%xx

为什么要使用这样的编码? 这是为了兼容一些设备,有些设备只能传ASCII码,只认识128个字符,不认识汉字。

C++编码解码实现

C++使用GBK编码

绝对不编码的,只有字母、数字、短横线(-)、下划线(_)、点(.)和波浪号(~),其他字符要视情况而定

unsigned char ToHex(unsigned char x) 
{ 
    return  x > 9 ? x + 55 : x + 48; 
}
 
unsigned char FromHex(unsigned char x) 
{ 
    unsigned char y;
    if (x >= 'A' && x <= 'Z') y = x - 'A' + 10;
    else if (x >= 'a' && x <= 'z') y = x - 'a' + 10;
    else if (x >= '0' && x <= '9') y = x - '0';
    else assert(0);
    return y;
}
 
std::string UrlEncode(const std::string& str)
{
    std::string strTemp = "";
    size_t length = str.length();
    for (size_t i = 0; i < length; i++)
    {
        if (isalnum((unsigned char)str[i]) || 
            (str[i] == '-') ||
            (str[i] == '_') || 
            (str[i] == '.') || 
            (str[i] == '~'))
            strTemp += str[i];
        else if (str[i] == ' ')
            strTemp += "+";
        else
        {
            strTemp += '%';
            strTemp += ToHex((unsigned char)str[i] >> 4);//高4位
            strTemp += ToHex((unsigned char)str[i] % 16);//低4w
        }
    }
    return strTemp;
}
 
std::string UrlDecode(const std::string& str)
{
    std::string strTemp = "";
    size_t length = str.length();
    for (size_t i = 0; i < length; i++)
    {
        if (str[i] == '+') strTemp += ' ';
        else if (str[i] == '%')
        {
            assert(i + 2 < length);
            unsigned char high = FromHex((unsigned char)str[++i]);
            unsigned char low = FromHex((unsigned char)str[++i]);
            strTemp += high*16 + low;
        }
        else strTemp += str[i];
    }
    return strTemp;
}

参考文章