1. 程式人生 > >【程式設計筆記】UNICODE和UTF-8和ASCII互轉

【程式設計筆記】UNICODE和UTF-8和ASCII互轉

最近維護一個專案時發現,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;
}