今天在windows控制臺(tái)上打印utf-8字符時(shí)出現(xiàn)了亂碼,然后就折騰了一下發(fā)現(xiàn)在簡(jiǎn)體中文版上的windows默認(rèn)的代碼頁(yè)是936(gbk編碼),在控制臺(tái)上輸入chcp 65001解決之(65001是UTF-8代碼頁(yè)編號(hào)),但是我這么愛鉆研(瞎折騰)怎么可能就這么完事了呢,就嘗試了下用C語(yǔ)言實(shí)現(xiàn)utf-8轉(zhuǎn)化成gbk編碼(還順便學(xué)習(xí)了下幾種編碼),下面是解決方法。
嗯。。還有我學(xué)習(xí)時(shí)看的一個(gè)資料,介紹編碼知識(shí)的
http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html
解決方法
1.使用代碼更改活動(dòng)代碼頁(yè)
system("chcp 65001");
也可以使用windows的一個(gè)API(設(shè)置輸出代碼頁(yè)),效果一樣
SetConsoleOutputCP(65001);
還有另外一個(gè)API是SetConsoleCP(),這個(gè)API設(shè)置的是輸入代碼頁(yè),在輸出時(shí)并不起作用
C語(yǔ)言標(biāo)準(zhǔn)里面還提供了一個(gè)函數(shù)來(lái)設(shè)置代碼頁(yè)Setlocale(),不過沒有測(cè)試過
2.將utf-8轉(zhuǎn)換成gbk編碼
原理是利用windows的兩個(gè)API,將UTF-8轉(zhuǎn)成unicode編碼,再轉(zhuǎn)成gbk編碼
下面是對(duì)兩個(gè)函數(shù)的介紹
函數(shù)原型
int MultiByteToWideChar(
UINT CodePage,
DWORD dwFlags,
LPCSTR lpMultiByteStr,
int cchMultiByte,
LPWSTR lpWideCharStr,
int cchWideChar);
函數(shù)功能?
該函數(shù)映射一個(gè)字符串到一個(gè)寬字符(unicode)的字符串。由該函數(shù)映射的字符串沒必要是多字節(jié)字符組。
參數(shù)
CodePage:指定執(zhí)行轉(zhuǎn)換的代碼頁(yè),這個(gè)參數(shù)可以為系統(tǒng)已安裝或有效的任何代碼頁(yè)所給定的值。我們用到的是下面兩個(gè)值(當(dāng)然你也可以指定別的值):
CP_ACP:ANSI代碼頁(yè)(簡(jiǎn)體中文Windows操作系統(tǒng)中,ANSI 編碼代表 GBK 編碼)
CP_UTF8:使用UTF-8轉(zhuǎn)換
dwFlags: 指定如何處理沒有轉(zhuǎn)換的字符,但不設(shè)此參數(shù)函數(shù)會(huì)運(yùn)行的更快一些,我都是把它設(shè)為0。 可設(shè)的值如下表所示:
WC_NO_BEST_FIT_CHARS
把不能直接轉(zhuǎn)換成相應(yīng)多字節(jié)字符的Unicode字符轉(zhuǎn)換成lpDefaultChar指定的默認(rèn)字符。也就是說,如果把Unicode轉(zhuǎn)換成多字節(jié)字符,然后再轉(zhuǎn)換回來(lái),你并不一定得到相同的Unicode字符,因?yàn)檫@期間可能使用了默認(rèn)字符。此選項(xiàng)可以單獨(dú)使用,也可以和其他選項(xiàng)一起使用。
WC_COMPOSITECHECK
把合成字符轉(zhuǎn)換成預(yù)制的字符。它可以與后三個(gè)選項(xiàng)中的任何一個(gè)組合使用,如果沒有與他們中的任何一個(gè)組合,則與選項(xiàng)WC_SEPCHARS相同。
WC_ERR_INVALID_CHARS
此選項(xiàng)會(huì)致使函數(shù)遇到無(wú)效字符時(shí)失敗返回,并且GetLastError會(huì)返回錯(cuò)誤碼ERROR_NO_UNICODE_TRANSLATION。否則函數(shù)會(huì)自動(dòng)丟棄非法字符。此選項(xiàng)只能用于UTF8。
WC_DISCARDNS? ?
轉(zhuǎn)換時(shí)丟棄不占空間的字符,與WC_COMPOSITECHECK 一起使用
WC_SEPCHARS
轉(zhuǎn)換時(shí)產(chǎn)生單獨(dú)的字符,此是默認(rèn)轉(zhuǎn)換選項(xiàng),WC_COMPOSITECHECK一起使用
WC_DEFAULTCHAR
轉(zhuǎn)換時(shí)使用默認(rèn)字符代替例外的字符,(最常見的如’?’),與WC_COMPOSITECHECK一起使用。
對(duì)于下列代碼頁(yè),dwFlags必須為0,否則函數(shù)返回錯(cuò)誤碼ERROR_INVALID_FLAGS。 50220 50221 50222 50225 50227 50229 52936 54936 57002到57011 65000(UTF7) 42(Symbol)
對(duì)于UTF8,dwFlags必須為0或WC_ERR_INVALID_CHARS,否則函數(shù)都將失敗返回并設(shè)置錯(cuò)誤碼ERROR_INVALID_FLAGS,你可以調(diào)用GetLastError獲得。
lpMultiByteStr:指向?qū)⒈晦D(zhuǎn)換字符串的字符。
cchMultiByte:指定由參數(shù)lpMultiByteStr指向的字符串中字節(jié)的個(gè)數(shù)。如果這個(gè)值為-1,字符串將被設(shè)定為以NULL為結(jié)束符的字符串,并且自動(dòng)計(jì)算長(zhǎng)度。
lpWideCharStr:指向接收被轉(zhuǎn)換字符串的緩沖區(qū)。
cchWideChar:指定由參數(shù)lpWideCharStr指向的緩沖區(qū)的字節(jié)個(gè)數(shù)。若此值為零,函數(shù)返回緩沖區(qū)所必需的寬字符數(shù),在這種情況下,lpWideCharStr中的緩沖區(qū)不被使用。
返回值:如果函數(shù)運(yùn)行成功,并且cchWideChar不為零,返回值是由lpWideCharStr指向的緩沖區(qū)中寫入的寬字符數(shù);如果函數(shù)運(yùn)行成功,并且cchMultiByte為零,返回值是接收到待轉(zhuǎn)換字符串的緩沖區(qū)所需求的寬字符數(shù)大小。如果函數(shù)運(yùn)行失敗,返回值為零。
函數(shù)原型
int WideCharToMultiByte(
UINT CodePage,
DWORD dwFlags,
LPCWSTR lpWideCharStr,
int cchWideChar,
LPSTR lpMultiByteStr,
int cbMultiByte,
LPCSTR lpDefaultChar,
LPBOOL lpUsedDefaultChar);
函數(shù)功能?
此函數(shù)把寬字符串轉(zhuǎn)換成指定的新的字符串,如ANSI,UTF8等,新字符串不必是多字節(jié)字符集。?
參數(shù)
lpWideCharStr : 待轉(zhuǎn)換的寬字符串。
cchWideChar : 待轉(zhuǎn)換寬字符串的長(zhǎng)度,-1表示轉(zhuǎn)換到字符串結(jié)尾。
lpMultiByteStr : 接收轉(zhuǎn)換后輸出新串的緩沖區(qū)。
cbMultiByte :輸出緩沖區(qū)大小,如果為0,lpMultiByteStr將被忽略,函數(shù)將返回所需緩沖區(qū)大小而不使用lpMultiByteStr。
lpDefaultChar : 指向字符的指針, 在指定編碼里找不到相應(yīng)字符時(shí)使用此字符作為默認(rèn)字符代替。如果為NULL則使用系統(tǒng)默認(rèn)字符。對(duì)于要求此參數(shù)為NULL的dwFlags而使用此參數(shù),函數(shù)將失敗返回并設(shè)置錯(cuò)誤碼ERROR_INVALID_PARAMETER。
lpUsedDefaultChar :開關(guān)變量的指針,用以表明是否使用過默認(rèn)字符。對(duì)于要求此參數(shù)為NULL的dwFlags而使用此參數(shù),函數(shù)將失敗返回并設(shè)置錯(cuò)誤碼ERROR_INVALID_PARAMETER。lpDefaultChar和lpUsedDefaultChar都設(shè)為NULL,函數(shù)會(huì)更快一些。
返回值 :如果函數(shù)成功,且cbMultiByte非0,返回寫入lpMultiByteStr的字節(jié)數(shù)(包括字符串結(jié)尾的null);cbMultiByte為0,則返回轉(zhuǎn)換所需字節(jié)數(shù)。函數(shù)失敗,返回0。
下面是簡(jiǎn)單的函數(shù)實(shí)現(xiàn)
void utf8ToGbk(char *utf8String, char *gbkString)
{
wchar_t *unicodeStr = NULL;
int nRetLen = 0;
nRetLen = MultiByteToWideChar(CP_UTF8, 0, utf8String, -1, NULL, 0);
//求需求的寬字符數(shù)大小
unicodeStr = (wchar_t *)malloc(nRetLen * sizeof(wchar_t));
nRetLen = MultiByteToWideChar(CP_UTF8, 0, utf8String, -1, unicodeStr, nRetLen);
//將utf-8編碼轉(zhuǎn)換成unicode編碼
nRetLen = WideCharToMultiByte(CP_ACP, 0, unicodeStr, -1, NULL, 0, NULL, 0);
//求轉(zhuǎn)換所需字節(jié)數(shù)
nRetLen = WideCharToMultiByte(CP_ACP, 0, unicodeStr, -1, gbkString, nRetLen, NULL, 0);
//unicode編碼轉(zhuǎn)換成gbk編碼
free(unicodeStr);
}
第三篇文章哈哈哈哈
人生是一場(chǎng)規(guī)模龐大的摸彩游戲,只有中獎(jiǎng)的彩票展現(xiàn)在我們眼前?!都埮频拿孛堋?/p>
給我點(diǎn)十個(gè)贊我就買杯可樂慶祝下