Unicode与UTF8相互转化(使用MultiByteToWideChar)
1、簡述
最近在發(fā)送網(wǎng)絡(luò)請求時遇到了中文字符亂碼的問題,在代碼中調(diào)試字符正常,用抓包工具抓的包中文字符顯示正常,就是發(fā)送到服務(wù)器就顯示亂碼了,那就要將客戶端和服務(wù)器設(shè)置統(tǒng)一的編碼(UTF-8),而我們程序中 一般用的是Unicode編碼,所以這就需要將中文字符轉(zhuǎn)為UTF-8格式的,其他英文字符和數(shù)字就不需要轉(zhuǎn)了。下面就講述一下方法。
2、代碼之路
Unicode 轉(zhuǎn) UTF-8
char* UnicodeToUtf8(const wchar_t* unicode)
{
int len;
len = WideCharToMultiByte(CP_UTF8, 0, unicode, -1, NULL, 0, NULL, NULL);
char *szUtf8 = (char*)malloc(len + 1);
memset(szUtf8, 0, len + 1);
WideCharToMultiByte(CP_UTF8, 0, unicode, -1, szUtf8, len, NULL, NULL);
return szUtf8;
}
int main(int argc, char *argv[])
{
wchar_t* wCharUnicode = L"中國";
char* cCharUtf = UnicodeToUtf8(wCharUnicode);
return 0;
}
結(jié)果如下:
我們看到轉(zhuǎn)為UTF-8之后在VS中查看時顯示為其他字符。為了驗證我們轉(zhuǎn)的字符是否正確,我們可以借用NotePad++這個工具。我們新建一個文件,用NotePad++打開,文件編碼默認為ANSI格式,這里顯示的跟VS中調(diào)試時顯示的值是一樣的。
我們修改文件編碼為UTF-8之后再看一下,是不是顯示正常了,所以驗證了轉(zhuǎn)換代碼正確。
UTF-8 轉(zhuǎn) Unicode
CString UTF82WCS(const char* szU8)
{
//預(yù)轉(zhuǎn)換,得到所需空間的大小;
int wcsLen = ::MultiByteToWideChar(CP_UTF8, NULL, szU8, strlen(szU8), NULL, 0);
//分配空間要給''留個空間,MultiByteToWideChar不會給''空間
wchar_t* wszString = new wchar_t[wcsLen + 1];
//轉(zhuǎn)換
::MultiByteToWideChar(CP_UTF8, NULL, szU8, strlen(szU8), wszString, wcsLen);
//最后加上''
wszString[wcsLen] = '';
CString unicodeString(wszString);
delete[] wszString;
wszString = NULL;
return unicodeString;
}
int main(int argc, char *argv[])
{
wchar_t* wCharUnicode = L"中國";
char* cCharUtf = UnicodeToUtf8(wCharUnicode);
CString strUnicode = UTF82WCS(cCharUtf);
return 0;
}
從結(jié)果中我們看到,成功地將UTF-8編碼轉(zhuǎn)為Unicode編碼,代碼很簡單,還是要多思考,多練,多查閱資料。
給出幾個小實例,看一下轉(zhuǎn)換結(jié)果。
下面為測試代碼:
實例一:
int length;
wchar_t* wCharUnicode = L"中國你好";
length = wcslen(wCharUnicode); // length = 4;
char* cCharUtf = UnicodeToUtf8(wCharUnicode);
length = strlen(cCharUtf); // length = 12;
// 將UTF格式的char*轉(zhuǎn)為CString
CString strUtf(cCharUtf);
length = strUtf.GetLength(); // length = 6;
CString strUnicode = UTF82WCS(cCharUtf);
length = strUnicode.GetLength(); // length = 4;
實例二:
int length;
wchar_t* wCharUnicode = L"中國,你好abc";
length = wcslen(wCharUnicode); // length = 8;
char* cCharUtf = UnicodeToUtf8(wCharUnicode);
length = strlen(cCharUtf); // length = 16;
// 將UTF格式的char*轉(zhuǎn)為CString
CString strUtf(cCharUtf);
length = strUtf.GetLength(); // length = 10;
CString strUnicode = UTF82WCS(cCharUtf);
length = strUnicode.GetLength(); // length = 8;
這里在中文 “中國”和“你好”之間加了英文的標(biāo)點符號,顯示正常。
實例三:
int length;
wchar_t* wCharUnicode = L"中國,你好abc";
length = wcslen(wCharUnicode); // length = 8;
char* cCharUtf = UnicodeToUtf8(wCharUnicode);
length = strlen(cCharUtf); // length = 18;
// 將UTF格式的char*轉(zhuǎn)為CString
CString strUtf(cCharUtf);
length = strUtf.GetLength(); // length = 10;
CString strUnicode = UTF82WCS(cCharUtf);
length = strUnicode.GetLength(); // length = 8;
這里在中文 “中國”和“你好”之間加了中文的標(biāo)點符號,cCharUtf 在VS中看不到值,但是可以轉(zhuǎn)成CString查看其值,結(jié)果正確。
尾
我們從三個不同實例的測試結(jié)果中看到一個中文字符或者中文標(biāo)點符號,占了三個字節(jié)(有資料顯示 UTF-8編碼:采用變長字節(jié) ,1 :ASCII, 2: 希臘字母, 3: 漢字, 4: 中日韓超大字符集,這里常用漢字占用3個,不常用的漢字占用4個字節(jié) ),中文標(biāo)點符號與英文標(biāo)點符號差了兩個字節(jié),這里要特別注意,而英文字符在UTF-8下都為一個字節(jié)。
同時我們可以看到用CString 類型變量來分別接收Unicode和UTF-8編碼的字符,這里我們看到長度不一致(這里特值字符長度,并不是字符所占字節(jié)數(shù)),雖然我們看到UTF-8編碼比Unicode編碼要長,但是并不是絕對的,因為UTF-8在存儲不同字符時所占的內(nèi)存大小不一樣,就比如存儲ASCII碼 就只需要一個字節(jié),而Unicode需要兩個字節(jié),關(guān)于編碼問題還是挺復(fù)雜的,而正是Unicode儲存ASCII也需要兩個字節(jié),這里就出現(xiàn)了UTF-8、UTF-16、UTF-32等不同的字符編碼格式,至于為什么會出現(xiàn)這么多的編碼格式,那也是因為每種編碼格式保存字符的空間大小不一致,就比如UTF-8保存一個英文字母只需要一個字節(jié),而Unicode需要兩個字節(jié),但是保存一個中文字符,UTF-8需要三個字節(jié),而Unicode則需要兩個字節(jié)。
UTF全稱為unicode transformation format,其實說白了,UTF-8就是Unicode的實現(xiàn)方式之一, ,UTF-8最大的一個特點,就是它是一種變長的編碼方式。它可以使用1~4個字節(jié)表示一個符號,根據(jù)不同的符號而變化字節(jié)長度。
網(wǎng)上也有好多關(guān)于字符問題的資料,但是說法不一,所以還是要經(jīng)過多方驗證,這里需要注意一下。
http://blog.csdn.net/goforwardtostep/article/details/53207804
總結(jié)
以上是生活随笔為你收集整理的Unicode与UTF8相互转化(使用MultiByteToWideChar)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【转载】目前国内主流的云服务器厂商有哪些
- 下一篇: cesium 学习(七) Heading