首頁 > 軟體

使用iconv進行編碼gb2312轉utf8 轉碼失敗及解決

2020-06-16 16:34:24

使用背景

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


IT145.com E-mail:sddin#qq.com