zoukankan      html  css  js  c++  java
  • 使用iconv进行编码gb2312转utf8 转码失败的坑

    iconv 编码gb2312转utf8 转码失败的坑

    使用背景

    项目中使用thrift进行C#程序调用c++接口,其中的协议是通过json进行传输的,由于默认thrift使用utf8进行传输,而C#和c++程序都默认使用多字节的编码方式,所以在传输前就需要对编码进行utf8的转换,而在接收处理的时候再转换成gb2312。

    问题

    bug发生在一个文件路径上面,包含文件路径就会导致c++端无法解析,但是纯中文和英文及不同字符都没有问题,所以一开始未怀疑是编码问题,经过调试最终确定问题在iconv转码上,在转码的时候转换失败,导致返回结果为空。

    分析

    文件名为"1癵鰢⑷}·ˇ々.mp4",其中包含有特殊汉字和字符,猜测为字符集无法表示导致转码失败。

    解决

    网上查询确实存在该问题,建议将编码gb2312换成 gb18030 以支持更多字符。

    原来的转码函数

    std::string ConvertCode::gbk2utf8(const std::string& strGbk)
    {
        return code_convert("gb2312", "utf-8", strGbk);
    }
    

    转变以后测试正常

    std::string ConvertCode::gbk2utf8(const std::string& strGbk)
    {
        return code_convert("gb18030", "utf-8", strGbk);
    }
    

    附iconv转变函数

    std::string ConvertCode::code_convert(char *source_charset, char *to_charset, const std::string& sourceStr)
    {
        iconv_t cd = iconv_open(to_charset, source_charset);//获取转换句柄,void*类型
        if (cd == 0)
            return "";
    
        size_t inlen = sourceStr.size();
    
        if (inlen == 0)
            return "";
    
        size_t outlen = inlen*2+1;
        const char* inbuf = (char*)sourceStr.c_str();
        char* outbuf = (char*)malloc(outlen);
        memset(outbuf, 0, outlen);
        char *poutbuf = outbuf; //多加这个转换是为了避免iconv这个函数出现char(*)[255]类型的实参与char**类型的形参不兼容
        if (iconv(cd, &inbuf, &inlen, &poutbuf, &outlen) == -1)
            return "";
    
        std::string strTemp(outbuf);//此时的strTemp为转换编码之后的字符串
        iconv_close(cd);
        return strTemp;
    }
  • 相关阅读:
    面向对象程序设计第五次作业
    C++第一次作业
    面向对象程序设计第四次作业
    面向对象程序设计第三次作业
    C++自学笔记(3)
    C++自学随笔(2)
    软件测试2019:第七次作业—— 用户体验测试
    软件测试2019:第八次作业—— 缺陷管理(含缺陷管理工具的配置实验)
    软件测试2019:第六次作业—— Web功能测试(含Selenium IDE实验)
    软件测试2019:第五次作业—— 安全测试(含安全测试工具实验)
  • 原文地址:https://www.cnblogs.com/chencarl/p/10694243.html
Copyright © 2011-2022 走看看