【程式設計筆記】UNICODE和UTF-8和ASCII互轉
阿新 • • 發佈:2019-02-18
最近維護一個專案時發現,MFC的Cstring型別寫到ini文字時,出現了亂碼。因為寫入的資料帶有類似的特殊字元❀,由於ini預設建立的編碼格式為GBK編碼格式,但是這個特殊字元在預設的GBK編碼下是不能識別的,會以?的形式存在。那這個特殊字元的編碼是什麼,暫時還沒搞清楚。但是既然知道存在這樣的bug,那麼我們就有了相應的解決方法:在寫入ini檔案時,先將unicode編碼的內容轉成utf-8(utf-8具有世界通用性,所以顯示這個特殊字元不在話下)再寫入到ini檔案,顯然在GBK編碼的ini檔案中顯示UTF-8編碼的內容肯定是亂碼,比如中文或者特殊字元。當我們要取出寫入ini檔案的內容時,我們又需要進行一次轉碼,將UTF-8轉成UNICODE編碼。
原始碼如下:
//UTF8轉Unicode std::wstring UTF8ToUnicode(const char* v_szUTF8) { std::wstring wstrUnicode; if(NULL == v_szUTF8) { return wstrUnicode; } DWORD dwNum = MultiByteToWideChar(CP_UTF8, 0, v_szUTF8, -1, NULL, 0); if(ERROR_NO_UNICODE_TRANSLATION == dwNum) { return wstrUnicode; } if(0 == dwNum) { return wstrUnicode; } WCHAR* wcsUnicode = new WCHAR[dwNum + 1]; memset(wcsUnicode, 0, (dwNum + 1) * sizeof(WCHAR)); MultiByteToWideChar(CP_UTF8, 0, v_szUTF8, -1, wcsUnicode ,dwNum); wstrUnicode = wcsUnicode; if(NULL != wcsUnicode) { delete [] wcsUnicode; } return wstrUnicode; }
//Unicode轉UTF8 std::string UnicodeToUTF8(const WCHAR* v_wcsUnicode) { std::string strUTF8; if(NULL == v_wcsUnicode) { return strUTF8; } DWORD dwNum = WideCharToMultiByte(CP_UTF8, 0, v_wcsUnicode, -1, NULL, 0, NULL, 0); if(0 == dwNum) { return strUTF8; } char* szUTF8 = new char[dwNum + 1]; memset(szUTF8, 0, (dwNum + 1) * sizeof(char)); //將寬位元組字串轉換為多位元組字串 WideCharToMultiByte(CP_UTF8, 0, v_wcsUnicode, -1, szUTF8, dwNum, NULL, 0); strUTF8 = szUTF8; if(NULL != szUTF8) { delete [] szUTF8; } return strUTF8; }
//Unicode轉ASCII
std::string UnicodeToASCII(const WCHAR* v_wcsUnicode)
{
std::string strASCII;
if(NULL == v_wcsUnicode)
{
return strASCII;
}
DWORD dwNum = WideCharToMultiByte(CP_OEMCP, 0, v_wcsUnicode, -1, NULL, 0, NULL, 0);
if(0 == dwNum)
{
return strASCII;
}
char* szASCII = new char[dwNum + 1];
memset(szASCII, 0, (dwNum + 1) * sizeof(char));
//將寬位元組字串轉換為多位元組字串
WideCharToMultiByte(CP_OEMCP, 0, v_wcsUnicode, -1, szASCII, dwNum, NULL, 0);
strASCII = szASCII;
if(NULL != szASCII)
{
delete [] szASCII;
}
return strASCII;
}
//ASCII轉Unicode
std::wstring ASCIIToUnicode(const char* v_szASCII)
{
std::wstring wstrUnicode;
if(NULL == v_szASCII)
{
return wstrUnicode;
}
DWORD dwNum = MultiByteToWideChar(CP_ACP, 0, v_szASCII, -1, NULL, 0);
if(ERROR_NO_UNICODE_TRANSLATION == dwNum)
{
return wstrUnicode;
}
if(0 == dwNum)
{
return wstrUnicode;
}
WCHAR* wcsUnicode = new WCHAR[dwNum + 1];
memset(wcsUnicode, 0, (dwNum + 1) * sizeof(WCHAR));
MultiByteToWideChar(CP_ACP, 0, v_szASCII, -1, wcsUnicode ,dwNum);
wstrUnicode = wcsUnicode;
if(NULL != wcsUnicode)
{
delete [] wcsUnicode;
}
return wstrUnicode;
}
//UTF8轉ASCII
std::string UTF8ToASCII(const char* v_szUTF8)
{
std::string strASCII;
if(NULL == v_szUTF8)
{
return strASCII;
}
//先把 utf8 轉為 unicode
std::wstring wstrUnicode = UTF8ToUnicode(v_szUTF8);
//最後把 unicode 轉為 ascii
strASCII = UnicodeToASCII(wstrUnicode.c_str());
return strASCII;
}
//ASCII轉UTF8
std::string ASCIIToUTF8(const char* v_szASCII)
{
std::string strUTF8;
if(NULL == v_szASCII)
{
return strUTF8;
}
//先把 ascii 轉為 unicode
std::wstring wstrUnicode = ASCIIToUnicode(v_szASCII);
//最後把 unicode 轉為 utf8
strUTF8 = UnicodeToUTF8(wstrUnicode.c_str());
return strUTF8;
}