使用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;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM