字符是各種文字和符號的總稱,包括各國家文字、標(biāo)點符號、圖形符號、數(shù)字等。字符集是多個字符的集合,字符集種類較多,每個字符集包含的字符個數(shù)不同,常見字符集名稱:ASCII字符集、GB2312字符集、BIG5字符集、 GB 18030字符集、Unicode字符集等。計算機(jī)要準(zhǔn)確的處理各種字符集文字,需要進(jìn)行字符編碼,以便計算機(jī)能夠識別和存儲各種文字。
中文文字?jǐn)?shù)目大,而且還分為簡體中文和繁體中文兩種不同書寫規(guī)則的文字,而計算機(jī)最初是按英語單字節(jié)字符設(shè)計的,因此,對中文字符進(jìn)行編碼,是中文信息交流的技術(shù)基礎(chǔ)。本文將按照字符集的時間順序討論幾種典型的字符集,選取幾種代表性的中文字符集,研究歷史由來、特點、技術(shù)特征。
漢字編碼范圍
名稱 第一字節(jié) 第二字節(jié)
GB2312 0xB0-0xF7(176-247) 0xA0-0xFE(160-254)
GBK 0x81-0xFE(129-254) 0x40-0xFE(64-254)
Big5 0x81-0xFE(129-255) 0x40-0x7E(64-126)
0xA1-0xFE(161-254)
ASCII 字符集
1.名稱的由來
ASCII(American Standard Code for Information Interchange,美國信息互換標(biāo)準(zhǔn)代碼)是基于羅馬字母表的一套電腦編碼系統(tǒng)。
2.特點
它主要用于顯示現(xiàn)代英語和其他西歐語言。它是現(xiàn)今最通用的單字節(jié)編碼系統(tǒng),并等同于國際標(biāo)準(zhǔn)ISO 646。
3.包含內(nèi)容
控制字符:回車鍵、退格、換行鍵等。
可顯示字符:英文大小寫字符、阿拉伯?dāng)?shù)字和西文符號
4.技術(shù)特征
7位(bits)表示一個字符,共128字符
5.ASCII擴(kuò)展字符集
7位編碼的字符集只能支持128個字符,為了表示更多的歐洲常用字符對ASCII進(jìn)行了擴(kuò)展,ASCII擴(kuò)展字符集使用8位(bits)表示一個字符,共256字符。
ASCII擴(kuò)展字符集比ASCII字符集擴(kuò)充出來的符號包括表格符號、計算符號、希臘字母和特殊的拉丁符號。
GB2312 字符集
1.名稱的由來
GB2312又稱為GB2312-80字符集,全稱為《信息交換用漢字編碼字符集·基本集》,由原中國國家標(biāo)準(zhǔn)總局發(fā)布,1981年5月1日實施。
2.特點
GB2312是中國國家標(biāo)準(zhǔn)的簡體中文字符集。它所收錄的漢字已經(jīng)覆蓋99.75%的使用頻率,基本滿足了漢字的計算機(jī)處理需要。在中國大陸和新加坡獲廣泛使用。
3.包含內(nèi)容
GB2312收錄簡化漢字及一般符號、序號、數(shù)字、拉丁字母、日文假名、希臘字母、俄文字母、漢語拼音符號、漢語注音字母,共 7445 個圖形字符。其中包括6763個漢字,其中一級漢字3755個,二級漢字3008個;包括拉丁字母、希臘字母、日文平假名及片假名字母、俄語西里爾字母在內(nèi)的682個全角字符。
4.技術(shù)特征
(1)分區(qū)表示:
GB2312中對所收漢字進(jìn)行了“分區(qū)”處理,每區(qū)含有94個漢字/符號。這種表示方式也稱為區(qū)位碼。
各區(qū)包含的字符如下:01-09區(qū)為特殊符號;16-55區(qū)為一級漢字,按拼音排序;56-87區(qū)為二級漢字,按部首/筆畫排序;10-15區(qū)及88-94區(qū)則未有編碼。
(2)雙字節(jié)表示
兩個字節(jié)中前面的字節(jié)為第一字節(jié),后面的字節(jié)為第二字節(jié)。習(xí)慣上稱第一字節(jié)為“高字節(jié)” ,而稱第二字節(jié)為“低字節(jié)”。
“高位字節(jié)”使用了0xA1-0xF7 (把01-87區(qū)(88-94區(qū)未有編碼)的區(qū)號加上0xA0),“低位字節(jié)”使用了0xA1-0xFE (把01-94加上0xA0)。
GB2312又稱國標(biāo)碼,由國家標(biāo)準(zhǔn)總局發(fā)布,1981年5月1日實施,通行于大陸。新加坡等地也使用此編碼。它是一個簡化字的編碼規(guī)范,當(dāng)然也包括其他的符號、字母、日文假名等,共7445個圖形字符,其中漢字占6763個。我們平時說6768個漢字,實際上里邊有5個編碼為空白,所以總共有6763個漢字。
GB2312規(guī)定“對任意一個圖形字符都采用兩個字節(jié)表示,每個字節(jié)均采用七位編碼表示”,習(xí)慣上稱第一個字節(jié)為“高字節(jié)”,第二個字節(jié)為“低字節(jié)”。GB2312中漢字的編碼范圍為,第一字節(jié)0xB0-0xF7(對應(yīng)十進(jìn)制為176-247),第二個字節(jié)0xA0-0xFE(對應(yīng)十進(jìn)制為160-254)。
GB2312將代碼表分為94個區(qū),對應(yīng)第一字節(jié)(0xa1-0xfe);每個區(qū)94個位(0xa1-0xfe),對應(yīng)第二字節(jié),兩個字節(jié)的值分別為區(qū)號值和位號值加32(2OH),因此也稱為區(qū)位碼。01-09區(qū)為符號、數(shù)字區(qū),16-87區(qū)為漢字區(qū)(0xb0-0xf7),10-15區(qū)、88-94區(qū)是有待進(jìn)一步標(biāo)準(zhǔn)化的空白區(qū)。
5.編碼舉例
以GB2312字符集的第一個漢字“啊”字為例,它的區(qū)號16,位號01,則區(qū)位碼是1601,在大多數(shù)計算機(jī)程序中,高字節(jié)和低字節(jié)分別加0xA0得到程序的漢字處理編碼0xB0A1。計算公式是:0xB0=0xA0+16, 0xA1=0xA0+1。“北京”的區(qū)位碼分別是:17 17 30 09 所以分別加上0xA0 0xA0 0xA0 0xA0,在內(nèi)存中顯示的16進(jìn)制是 B1 B1 BE A9
GBK 字符集
1.名稱的由來
GBK是GB2312的擴(kuò)展,是向上兼容的,因此GB2312中的漢字的編碼與GBK中漢字的相同。另外,GBK中還包含繁體字的編碼,它與Big5編碼之間的關(guān)系我還沒有弄明白,好像是不一致的。
2. 特點
GBK中每個漢字仍然包含兩個字節(jié),第一個字節(jié)的范圍是0x81-0xFE(即129-254),第二個字節(jié)的范圍是0x40-0xFE(即64-254)。GBK中有碼位23940個,包含漢字21003個。
BIG5 字符集
1.名稱的由來
又稱大五碼或五大碼,1984年由臺灣財團(tuán)法人信息工業(yè)策進(jìn)會和五間軟件公司宏碁 (Acer)、神通 (MiTAC)、佳佳、零壹 (Zero One)、大眾 (FIC)創(chuàng)立,故稱大五碼。
Big5碼的產(chǎn)生,是因為當(dāng)時臺灣不同廠商各自推出不同的編碼,如倚天碼、IBM PS55、王安碼等,彼此不能兼容;另一方面,臺灣政府當(dāng)時尚未推出官方的漢字編碼,而中國大陸的GB2312編碼亦未有收錄繁體中文字。
2.特點
Big5字符集共收錄13,053個中文字,該字符集在中國臺灣使用。耐人尋味的是該字符集重復(fù)地收錄了兩個相同的字:“兀”(0xA461及0xC94A)、“嗀”(0xDCD1及0xDDFC)。
3.字符編碼方法
Big5碼使用了雙字節(jié)儲存方法,以兩個字節(jié)來編碼一個字。第一個字節(jié)稱為“高位字節(jié)”,第二個字節(jié)稱為“低位字節(jié)”。高位字節(jié)的編碼范圍0xA1-0xF9,低位字節(jié)的編碼范圍0x40-0x7E及0xA1-0xFE。
各編碼范圍對應(yīng)的字符類型如下:0xA140-0xA3BF為標(biāo)點符號、希臘字母及特殊符號,另外于0xA259-0xA261,存放了雙音節(jié)度量衡單位用字:兙兛兞兝兡兣嗧瓩糎;0xA440-0xC67E為常用漢字,先按筆劃再按部首排序;0xC940-0xF9D5為次常用漢字,亦是先按筆劃再按部首排序。
4.Big5 的局限性
盡管Big5碼內(nèi)包含一萬多個字符,但是沒有考慮社會上流通的人名、地名用字、方言用字、化學(xué)及生物科等用字,沒有包含日文平假名及片假名字母。
例如臺灣視“著”為“著”的異體字,故沒有收錄“著”字。康熙字典中的一些部首用字(如“亠”、“疒”、“辵”、“癶”等)、常見的人名用字(如“堃”、“煊”、“栢”、“喆”等) 也沒有收錄到Big5之中。
GB18030 字符集
1.名稱的由來
GB 18030的全稱是GB18030-2000《信息交換用漢字編碼字符集基本集的擴(kuò)充》,是我國政府于2000年3月17日發(fā)布的新的漢字編碼國家標(biāo)準(zhǔn),2001年8月31日后在中國市場上發(fā)布的軟件必須符合本標(biāo)準(zhǔn)
2.特點
GB 18030字符集標(biāo)準(zhǔn)的出臺經(jīng)過廣泛參與和論證,來自國內(nèi)外知名信息技術(shù)行業(yè)的公司,信息產(chǎn)業(yè)部和原國家質(zhì)量技術(shù)監(jiān)督局聯(lián)合實施。
GB 18030字符集標(biāo)準(zhǔn)解決漢字、日文假名、朝鮮語和中國少數(shù)民族文字組成的大字符集計算機(jī)編碼問題。該標(biāo)準(zhǔn)的字符總編碼空間超過150萬個編碼位,收錄了27484個漢字,覆蓋中文、日文、朝鮮語和中國少數(shù)民族文字。滿足中國大陸、香港、臺灣、日本和韓國等東亞地區(qū)信息交換多文種、大字量、多用途、統(tǒng)一編碼格式的要求。并且與Unicode 3.0版本兼容,填補(bǔ)Unicode擴(kuò)展字符字匯“統(tǒng)一漢字?jǐn)U展A”的內(nèi)容。并且與以前的國家字符編碼標(biāo)準(zhǔn)(GB2312,GB13000.1)兼容。
3.編碼方法
GB 18030標(biāo)準(zhǔn)采用單字節(jié)、雙字節(jié)和四字節(jié)三種方式對字符編碼。單字節(jié)部分使用0×00至0×7F碼(對應(yīng)于ASCII碼的相應(yīng)碼)。雙字節(jié)部分,首字節(jié)碼從0×81至0×FE,尾字節(jié)碼位分別是0×40至0×7E和0×80至0×FE。四字節(jié)部分采用GB/T 11383未采用的0×30到0×39作為對雙字節(jié)編碼擴(kuò)充的后綴,這樣擴(kuò)充的四字節(jié)編碼,其范圍為0×81308130到0×FE39FE39。其中第一、三個字節(jié)編碼碼位均為0×81至0×FE,第二、四個字節(jié)編碼碼位均為0×30至0×39。
4.包含的內(nèi)容
雙字節(jié)部分收錄內(nèi)容主要包括GB13000.1全部CJK漢字20902個、有關(guān)標(biāo)點符號、表意文字描述符13個、增補(bǔ)的漢字和部首/構(gòu)件80個、雙字節(jié)編碼的歐元符號等。 四字節(jié)部分收錄了上述雙字節(jié)字符之外的,包括CJK統(tǒng)一漢字?jǐn)U充A在內(nèi)的GB 13000.1中的全部字符。
對漢字進(jìn)行hash
為了處理漢字的方便,在查找漢字的時候,我們通常會用到hash的方法,那怎么來確定一個漢字位置呢?這就和每種編碼的排列有關(guān)了,這里主要給出一種hash函數(shù)的策略。
對于GB2312編碼,設(shè)輸入的漢字為GBword,我們可以采用公式(C1-176)*94 + (C2-161)確定GBindex。其中,C1表示第一字節(jié),C2表示第二字節(jié)。具體如下:
GBindex = ((unsigned char)GBword.at(0)-176)*94 + (unsigned char)GBword.at(1) - 161;
之所以用unsigned char類型,是因為char是一個字節(jié),如果用unsigend int,因為int是4個字節(jié)的,所以會造成擴(kuò)展,導(dǎo)致錯誤。
對于GBK編碼,設(shè)輸入的漢字為GBKword,則可以采用公式 index=(ch1-0x81)*190+(ch2-0x40)-(ch2/128),其中ch1是第一字節(jié),ch2是第二字節(jié)。
具體的,
GBKindex = ((unsigned char)GBKword[0]-129)*190 +
((unsigned char)GBKword[1]-64) - (unsigned char)GBKword[1]/128;
怎樣判斷一個漢字的是什么編碼
直接根據(jù)漢字的編碼范圍判斷,對于GB2312和GBK可用下面兩個程序?qū)崿F(xiàn)。
1、判斷是否是GB2312
bool isGBCode(const string& strIn)
{
unsigned char ch1;
unsigned char ch2;
if (strIn.size() >= 2)
{
ch1 = (unsigned char)strIn.at(0);
ch2 = (unsigned char)strIn.at(1);
if (ch1>=176 && ch1<=247 && ch2>=160 && ch2<=254)
return true;
else return false;
}
else return false;
}
2、判斷是否是GBK編碼
bool isGBKCode(const string& strIn)
{
unsigned char ch1;
unsigned char ch2;
if (strIn.size() >= 2)
{
ch1 = (unsigned char)strIn.at(0);
ch2 = (unsigned char)strIn.at(1);
if (ch1>=129 && ch1<=254 && ch2>=64 && ch2<=254)
return true;
else return false;
}
else return false;
}
3、對于Big5
它的范圍為:高字節(jié)從0xA0到0xFE,低字節(jié)從0x40到0x7E,和0xA1到0xFE兩部分。判斷一個漢字是否是BIG5編碼,可以如上對字符的編碼范圍判斷即可。如何定位呢?那么也想象所有編碼排列為一個二維坐標(biāo),縱坐標(biāo)是高字節(jié),橫坐標(biāo)是低字節(jié)。這樣一行上的漢字個數(shù):(0x7E-0x40+1)+(0xFE-0xA1+1)=157。那么定位算法分兩塊,為:
if 0x40<=ch2<=0x7E: #is big5 char
index=((ch1-0xA1)*157+(ch2-0x40))*2
elif 0xA1<=ch2<=0xFE: #is big5 char
index=((ch1-0xA1)*157+(ch2-0xA1+63))*2
對于第二塊,計算偏移量時因為有兩塊數(shù)值,所以在計算后面一段值時,不要忘了前面還有一段值。0x7E-0x40+1=63。
如果判斷一個字符是西文字符還是中文字符
大家知道西文字符主要是指ASCII碼,它用一個字節(jié)表示。且這個字符轉(zhuǎn)換成數(shù)字之后,該數(shù)字是大于0的,而漢字是兩個字節(jié)的,第一個字節(jié)的轉(zhuǎn)化為數(shù)字之后應(yīng)該是小于0的,因此可以根據(jù)每個字節(jié)轉(zhuǎn)化為數(shù)字之后是否小于0,判斷它是否是漢字。
例如,設(shè)輸入字為strin,則,
If (strin.at(0) < 0)
cout << ”是漢字” << endl;
else cout << ”不是漢字” << endl;
編碼表
Unicode字符集
1.名稱的由來
Unicode字符集編碼是Universal Multiple-Octet Coded Character Set 通用多八位編碼字符集的簡稱,是由一個名為 Unicode 學(xué)術(shù)學(xué)會(Unicode Consortium)的機(jī)構(gòu)制訂的字符編碼系統(tǒng),支持現(xiàn)今世界各種不同語言的書面文本的交換、處理及顯示。該編碼于1990年開始研發(fā),1994年正式公布,最新版本是2005年3月31日的Unicode 4.1.0。
2.特征
Unicode是一種在計算機(jī)上使用的字符編碼。它為每種語言中的每個字符設(shè)定了統(tǒng)一并且唯一的二進(jìn)制編碼,以滿足跨語言、跨平臺進(jìn)行文本轉(zhuǎn)換、處理的要求。
3.編碼方法
Unicode 標(biāo)準(zhǔn)始終使用十六進(jìn)制數(shù)字,而且在書寫時在前面加上前綴“U+”,例如字母“A”的編碼為 004116 和字符“?”的編碼為 20AC16。所以“A”的編碼書寫為“U+0041”。
4.UTF-8 編碼
UTF-8是Unicode的其中一個使用方式。 UTF是 Unicode Translation Format,即把Unicode轉(zhuǎn)做某種格式的意思。
UTF-8便于不同的計算機(jī)之間使用網(wǎng)絡(luò)傳輸不同語言和編碼的文字,使得雙字節(jié)的Unicode能夠在現(xiàn)存的處理單字節(jié)的系統(tǒng)上正確傳輸。
UTF-8使用可變長度字節(jié)來儲存 Unicode字符,例如ASCII字母繼續(xù)使用1字節(jié)儲存,重音文字、希臘字母或西里爾字母等使用2字節(jié)來儲存,而常用的漢字就要使用3字節(jié)。輔助平面字符則使用4字節(jié)。
5.UTF-16 和 UTF-32 編碼
UTF-32、UTF-16 和 UTF-8 是 Unicode 標(biāo)準(zhǔn)的編碼字符集的字符編碼方案,UTF-16 使用一個或兩個未分配的 16 位代碼單元的序列對 Unicode 代碼點進(jìn)行編碼;UTF-32 即將每一個 Unicode 代碼點表示為相同值的 32 位整數(shù)
Ansi、Unicode、UTF8字符串之間的轉(zhuǎn)換和寫入文本文件
Ansi字符串我們最熟悉,英文占一個字節(jié),漢字2個字節(jié),以一個\0結(jié)尾,常用于txt文本文件
Unicode 字符串,每個字符(漢字、英文字母)都占2個字節(jié),以2個連續(xù)的\0結(jié)尾,NT操作系統(tǒng)內(nèi)核用的是這種字符串,常被定義為typedef unsigned short wchar_t;所以我們有時常會見到什么char*無法轉(zhuǎn)換為unsigned short*之類的錯誤,其實就是unicode
UTF8是Unicode一種壓縮形式,英文A在unicode中表示為0x0041,老外覺得這種存儲方式太浪費,因為浪費了50%的空間,于是就把英文壓縮成1個字節(jié),成了utf8編碼,但是漢字在utf8中占3個字節(jié),顯然用做中文不如 ansi合算,這就是中國的網(wǎng)頁用作ansi編碼而老外的網(wǎng)頁常用utf8的原因。
UTF8在還游戲里運用的很廣泛,比如WOW的lua腳本等
下面來說一下轉(zhuǎn)換,主要用代碼來說明吧
寫文件我用了CFile類,其實用FILE*之類的也是一樣,寫文件和字符串什么類別沒有關(guān)系,硬件只關(guān)心數(shù)據(jù)和長度
bool IsUTF8(const void* pBuffer, long size)
{
bool IsUTF8 = true;
unsigned char* start = (unsigned char*)pBuffer;
unsigned char* end = (unsigned char*)pBuffer + size;
while (start < end)
{
if (*start < 0x80) // (10000000): 值小于0x80的為ASCII字符
{
start++;
}
else if (*start < (0xC0)) // (11000000): 值介于0x80與0xC0之間的為無效UTF-8字符
{
IsUTF8 = false;
break;
}
else if (*start < (0xE0)) // (11100000): 此范圍內(nèi)為2字節(jié)UTF-8字符
{
if (start >= end - 1)
break;
if ((start[1] & (0xC0)) != 0x80)
{
IsUTF8 = false;
break;
}
start += 2;
}
else if (*start < (0xF0)) // (11110000): 此范圍內(nèi)為3字節(jié)UTF-8字符
{
if (start >= end - 2)
break;
if ((start[1] & (0xC0)) != 0x80 || (start[2] & (0xC0)) != 0x80)
{
IsUTF8 = false;
break;
}
start += 3;
}
else
{
IsUTF8 = false;
break;
}
}
return IsUTF8;
}
Ansi轉(zhuǎn)Unicode
介紹2種方法
void CConvertDlg::OnBnClickedButtonAnsiToUnicode()


{
// ansi to unicode
char* szAnsi = "abcd1234你我他";
//預(yù)轉(zhuǎn)換,得到所需空間的大小
int wcsLen = ::MultiByteToWideChar(CP_ACP, NULL, szAnsi, strlen(szAnsi), NULL, 0);
//分配空間要給'\0'留個空間,MultiByteToWideChar不會給'\0'空間
wchar_t* wszString = new wchar_t[wcsLen + 1];
//轉(zhuǎn)換
::MultiByteToWideChar(CP_ACP, NULL, szAnsi, strlen(szAnsi), wszString, wcsLen);
//最后加上'\0'
wszString[wcsLen] = '\0';
//unicode版的MessageBox API
::MessageBoxW(GetSafeHwnd(), wszString, wszString, MB_OK);

//接下來寫入文本
//寫文本文件,頭2個字節(jié)0xfeff,低位0xff寫在前
CFile cFile;
cFile.Open(_T("1.txt"), CFile::modeWrite | CFile::modeCreate);
//文件開頭
cFile.SeekToBegin();
cFile.Write("\xff\xfe", 2);
//寫入內(nèi)容
cFile.Write(wszString, wcsLen * sizeof(wchar_t));
cFile.Flush();
cFile.Close();
delete[] wszString;
wszString =NULL;


//方法2
//設(shè)置當(dāng)前地域信息,不設(shè)置的話,使用這種方法,中文不會正確顯示
//需要#include<locale.h>
setlocale(LC_CTYPE, "chs");
wchar_t wcsStr[100];
//注意下面是大寫S,在unicode中,代表后面是ansi字符串
//swprintf是sprintf的unicode版本
//格式的前面要加大寫L,代表是unicode
swprintf(wcsStr, L"%S", szAnsi);
::MessageBoxW(GetSafeHwnd(), wcsStr, wcsStr, MB_OK);

}
Unicode轉(zhuǎn)Ansi
也是2種方法
void CConvertDlg::OnBnClickedButtonUnicodeToAnsi()


{
// unicode to ansi
wchar_t* wszString = L"abcd1234你我他";
//預(yù)轉(zhuǎn)換,得到所需空間的大小,這次用的函數(shù)和上面名字相反
int ansiLen = ::WideCharToMultiByte(CP_ACP, NULL, wszString, wcslen(wszString), NULL, 0, NULL, NULL);
//同上,分配空間要給'\0'留個空間
char* szAnsi = new char[ansiLen + 1];
//轉(zhuǎn)換
//unicode版對應(yīng)的strlen是wcslen
::WideCharToMultiByte(CP_ACP, NULL, wszString, wcslen(wszString), szAnsi, ansiLen, NULL, NULL);
//最后加上'\0'
szAnsi[ansiLen] = '\0';
//Ansi版的MessageBox API
::MessageBoxA(GetSafeHwnd(), szAnsi, szAnsi, MB_OK);

//接下來寫入文本
//寫文本文件,ANSI文件沒有BOM
CFile cFile;
cFile.Open(_T("1.txt"), CFile::modeWrite | CFile::modeCreate);
//文件開頭
cFile.SeekToBegin();
//寫入內(nèi)容
cFile.Write(szAnsi, ansiLen * sizeof(char));
cFile.Flush();
cFile.Close();
delete[] szAnsi;
szAnsi =NULL;


//方法2
//和上面一樣有另一種方法
setlocale(LC_CTYPE, "chs");
char szStr[100];
//注意下面是大寫,在ansi中,代表后面是unicode字符串
//sprintf
sprintf(szStr, "%S", wszString);
::MessageBoxA(GetSafeHwnd(), szStr, szStr, MB_OK);
}
Unicode轉(zhuǎn)UTF8
void CConvertDlg::OnBnClickedButtonUnicodeToU8()


{
// unicode to UTF8
wchar_t* wszString = L"abcd1234你我他";
//預(yù)轉(zhuǎn)換,得到所需空間的大小,這次用的函數(shù)和上面名字相反
int u8Len = ::WideCharToMultiByte(CP_UTF8, NULL, wszString, wcslen(wszString), NULL, 0, NULL, NULL);
//同上,分配空間要給'\0'留個空間
//UTF8雖然是Unicode的壓縮形式,但也是多字節(jié)字符串,所以可以以char的形式保存
char* szU8 = new char[u8Len + 1];
//轉(zhuǎn)換
//unicode版對應(yīng)的strlen是wcslen
::WideCharToMultiByte(CP_UTF8, NULL, wszString, wcslen(wszString), szU8, u8Len, NULL, NULL);
//最后加上'\0'
szU8[u8Len] = '\0';
//MessageBox不支持UTF8,所以只能寫文件

//接下來寫入文本
//寫文本文件,UTF8的BOM是0xbfbbef
CFile cFile;
cFile.Open(_T("1.txt"), CFile::modeWrite | CFile::modeCreate);
//文件開頭
cFile.SeekToBegin();
//寫B(tài)OM,同樣低位寫在前
cFile.Write("\xef\xbb\xbf", 3);
//寫入內(nèi)容
cFile.Write(szU8, u8Len * sizeof(char));
cFile.Flush();
cFile.Close();
delete[] szU8;
szU8 =NULL;

}
UTF8轉(zhuǎn)UNICODE
void CConvertDlg::OnBnClickedButtonU8ToUnicode()


{
//UTF8 to Unicode
//由于中文直接復(fù)制過來會成亂碼,編譯器有時會報錯,故采用16進(jìn)制形式
char* szU8 = "abcd1234\xe4\xbd\xa0\xe6\x88\x91\xe4\xbb\x96\x00";
//預(yù)轉(zhuǎn)換,得到所需空間的大小
int wcsLen = ::MultiByteToWideChar(CP_UTF8, NULL, szU8, strlen(szU8), NULL, 0);
//分配空間要給'\0'留個空間,MultiByteToWideChar不會給'\0'空間
wchar_t* wszString = new wchar_t[wcsLen + 1];
//轉(zhuǎn)換
::MultiByteToWideChar(CP_UTF8, NULL, szU8, strlen(szU8), wszString, wcsLen);
//最后加上'\0'
wszString[wcsLen] = '\0';
//unicode版的MessageBox API
::MessageBoxW(GetSafeHwnd(), wszString, wszString, MB_OK);

//寫文本同ansi to unicode
}