轉(zhuǎn)載請(qǐng)注明出處http://www.cppblog.com/greatws/archive/2008/08/31/60546.html
最近有人問我關(guān)于這個(gè)的問題,就此寫一篇blog
Ansi字符串我們最熟悉,英文占一個(gè)字節(jié),漢字2個(gè)字節(jié),以一個(gè)\0結(jié)尾,常用于txt文本文件
Unicode字符串,每個(gè)字符(漢字、英文字母)都占2個(gè)字節(jié),以2個(gè)連續(xù)的\0結(jié)尾,NT操作系統(tǒng)內(nèi)核用的是這種字符串,常被定義為typedef unsigned short wchar_t;所以我們有時(shí)常會(huì)見到什么char*無法轉(zhuǎn)換為unsigned short*之類的錯(cuò)誤,其實(shí)就是unicode
UTF8是Unicode一種壓縮形式,英文A在unicode中表示為0x0041,老外覺得這種存儲(chǔ)方式太浪費(fèi),因?yàn)槔速M(fèi)了50%的空間,于是就把英文壓縮成1個(gè)字節(jié),成了utf8編碼,但是漢字在utf8中占3個(gè)字節(jié),顯然用做中文不如ansi合算,這就是中國的網(wǎng)頁用作ansi編碼而老外的網(wǎng)頁常用utf8的原因。
UTF8在還游戲里運(yùn)用的很廣泛,比如WOW的lua腳本等
下面來說一下轉(zhuǎn)換,主要用代碼來說明吧
寫文件我用了CFile類,其實(shí)用FILE*之類的也是一樣,寫文件和字符串什么類別沒有關(guān)系,硬件只關(guān)心數(shù)據(jù)和長(zhǎng)度
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'留個(gè)空間,MultiByteToWideChar不會(huì)給'\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個(gè)字節(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è)置的話,使用這種方法,中文不會(huì)正確顯示
????
//
需要#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'留個(gè)空間
????char*?szAnsi?=?new?char[ansiLen?+?1];
????//轉(zhuǎn)換
????//unicode版對(duì)應(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'留個(gè)空間
????//UTF8雖然是Unicode的壓縮形式,但也是多字節(jié)字符串,所以可以以char的形式保存
????char*?szU8?=?new?char[u8Len?+?1];
????//轉(zhuǎn)換
????//unicode版對(duì)應(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ù)制過來會(huì)成亂碼,編譯器有時(shí)會(huì)報(bào)錯(cuò),故采用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'留個(gè)空間,MultiByteToWideChar不會(huì)給'\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
}

Ansi轉(zhuǎn)換utf8和utf8轉(zhuǎn)換Ansi就是上面2個(gè)的結(jié)合,把unicode作為中間量,進(jìn)行2次轉(zhuǎn)換即可
by greatws