Unicode與UTF8相互轉化(使用MultiByteToWideChar)


1、簡述

最近在發送網絡請求時遇到了中文字符亂碼的問題,在代碼中調試字符正常,用抓包工具抓的包中文字符顯示正常,就是發送到服務器就顯示亂碼了,那就要將客戶端和服務器設置統一的編碼(UTF-8),而我們程序中 一般用的是Unicode編碼,所以這就需要將中文字符轉為UTF-8格式的,其他英文字符和數字就不需要轉了。下面就講述一下方法。

2、代碼之路

Unicode 轉 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; }

結果如下:

這里寫圖片描述

我們看到轉為UTF-8之后在VS中查看時顯示為其他字符。為了驗證我們轉的字符是否正確,我們可以借用NotePad++這個工具。我們新建一個文件,用NotePad++打開,文件編碼默認為ANSI格式,這里顯示的跟VS中調試時顯示的值是一樣的。

這里寫圖片描述

我們修改文件編碼為UTF-8之后再看一下,是不是顯示正常了,所以驗證了轉換代碼正確。 
這里寫圖片描述


UTF-8 轉 Unicode

CString UTF82WCS(const char* szU8) { //預轉換,得到所需空間的大小; int wcsLen = ::MultiByteToWideChar(CP_UTF8, NULL, szU8, strlen(szU8), NULL, 0); //分配空間要給'\0'留個空間,MultiByteToWideChar不會給'\0'空間 wchar_t* wszString = new wchar_t[wcsLen + 1]; //轉換 ::MultiByteToWideChar(CP_UTF8, NULL, szU8, strlen(szU8), wszString, wcsLen); //最后加上'\0' wszString[wcsLen] = '\0'; 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; }

這里寫圖片描述

從結果中我們看到,成功地將UTF-8編碼轉為Unicode編碼,代碼很簡單,還是要多思考,多練,多查閱資料。


給出幾個小實例,看一下轉換結果。

下面為測試代碼:

實例一:

int length; wchar_t* wCharUnicode = L"中國你好"; length = wcslen(wCharUnicode); // length = 4; char* cCharUtf = UnicodeToUtf8(wCharUnicode); length = strlen(cCharUtf); // length = 12; // 將UTF格式的char*轉為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*轉為CString CString strUtf(cCharUtf); length = strUtf.GetLength(); // length = 10; CString strUnicode = UTF82WCS(cCharUtf); length = strUnicode.GetLength(); // length = 8;

 

這里寫圖片描述

這里在中文 “中國”和“你好”之間加了英文的標點符號,顯示正常。

實例三:

int length; wchar_t* wCharUnicode = L"中國,你好abc"; length = wcslen(wCharUnicode); // length = 8; char* cCharUtf = UnicodeToUtf8(wCharUnicode); length = strlen(cCharUtf); // length = 18; // 將UTF格式的char*轉為CString CString strUtf(cCharUtf); length = strUtf.GetLength(); // length = 10; CString strUnicode = UTF82WCS(cCharUtf); length = strUnicode.GetLength(); // length = 8;

 

這里寫圖片描述

這里在中文 “中國”和“你好”之間加了中文的標點符號,cCharUtf 在VS中看不到值,但是可以轉成CString查看其值,結果正確。


我們從三個不同實例的測試結果中看到一個中文字符或者中文標點符號,占了三個字節(有資料顯示 UTF-8編碼:采用變長字節 ,1 :ASCII, 2: 希臘字母, 3: 漢字, 4: 中日韓超大字符集,這里常用漢字占用3個,不常用的漢字占用4個字節 ),中文標點符號與英文標點符號差了兩個字節,這里要特別注意,而英文字符在UTF-8下都為一個字節。

同時我們可以看到用CString 類型變量來分別接收UnicodeUTF-8編碼的字符,這里我們看到長度不一致這里特值字符長度,並不是字符所占字節數),雖然我們看到UTF-8編碼比Unicode編碼要長,但是並不是絕對的,因為UTF-8在存儲不同字符時所占的內存大小不一樣,就比如存儲ASCII碼 就只需要一個字節,而Unicode需要兩個字節,關於編碼問題還是挺復雜的,而正是Unicode儲存ASCII也需要兩個字節,這里就出現了UTF-8、UTF-16、UTF-32等不同的字符編碼格式,至於為什么會出現這么多的編碼格式,那也是因為每種編碼格式保存字符的空間大小不一致,就比如UTF-8保存一個英文字母只需要一個字節,而Unicode需要兩個字節,但是保存一個中文字符,UTF-8需要三個字節,而Unicode則需要兩個字節。

UTF全稱為unicode transformation format,其實說白了,UTF-8就是Unicode的實現方式之一, ,UTF-8最大的一個特點,就是它是一種變長的編碼方式。它可以使用1~4個字節表示一個符號,根據不同的符號而變化字節長度。

網上也有好多關於字符問題的資料,但是說法不一,所以還是要經過多方驗證,這里需要注意一下。

 

http://blog.csdn.net/goforwardtostep/article/details/53207804


免責聲明!

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



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