什么是ANSI,什么又是UNICODE呢?其實(shí)這是兩種不同的編碼方式標(biāo)準(zhǔn),ANSI中的字符采用8bit,而UNICODE中的字符采用16bit。(對于字符來說ANSI以單字節(jié)存放英文字符,以雙字節(jié)存放中文等字符,而Unicode下,英文和中文的字符都以雙字節(jié)存放)Unicode碼也是一種國際標(biāo)準(zhǔn)編碼,采用二個(gè)字節(jié)編碼,與ANSI碼不兼容。目前,在網(wǎng)絡(luò)、Windows系統(tǒng)和很多大型軟件中得到應(yīng)用。8bit的ANSI編碼只能表示256種字符,表示26個(gè)英文字母是綽綽有余的,但是表示漢字,韓國語等有著成千上萬個(gè)字符的非西方字符肯定就不夠了,正是如此才引入了UNICODE標(biāo)準(zhǔn)。???
???? 在軟件開發(fā)中,特別是使用C語言的一些有關(guān)字符串處理的函數(shù),ANSI和UNICODE是區(qū)分是用的,那么ANSI類型的字符和UNICODE類型的字符如何定義,如何使用呢?ANSI和UNICODE又如何轉(zhuǎn)換呢????
?? 一.定義部分:??
?? ANSI:char??? str[1024]; 可用字符串處理函數(shù):strcpy( ),??? strcat( ),?? strlen( )等等。
UNICODE:wchar_t??? str[1024];可用字符串處理函數(shù)???
二.可用函數(shù):
?? ANSI:即char,可用字符串處理函數(shù):strcat(??? ),strcpy(??? ),??? strlen(??? )等以str打頭的函數(shù)。???
?? UNICODE:即wchar_t 可用字符串處理函數(shù):wcscat(),wcscpy(),wcslen()等以wcs打頭的函數(shù)。???
?? 三.系統(tǒng)支持??
????? Windows??? 98??? :只支持ANSI。???
????? Windows??? 2k??? :既支持ANSI又支持UNICODE。???
????? Windows??? CE??? :只支持UNICODE。???
????? 說明???
????? 1 在COM里面只支持UNICODE。???
????? 2.Windows?? 2000整個(gè)OS系統(tǒng)都是基于UNICODE的,為此在windows 2000 下使用ANSI是需要付出代價(jià)的,雖然在編碼上不用任何的轉(zhuǎn)換,但是這種轉(zhuǎn)化是隱藏的,是占用系統(tǒng)資源的(CPU,內(nèi)存)。???
????? 3 在Windows 98下必須使用UNICODE,則需要自己手動(dòng)的編碼切換。???
??? 四.如何區(qū)分:???
??? 在我們軟件開發(fā)中往往需要即支持ANSI又支持UNICODE,不可能在要求類型轉(zhuǎn)換的時(shí)候,重新改變字符串的類型,和使用于字符串上的操作函數(shù)。為此, 標(biāo)準(zhǔn)C運(yùn)行期庫和Windows 提供了宏定義的方式。???
??? 在C語言里面提供了 _UNICODE宏(有下劃線),在Windows里面提供了UNICODE宏(無下劃線),只要定了_UNICODE宏和UNICODE宏,系統(tǒng)就會自動(dòng)切換到UNICODE版本,否則,系統(tǒng)按照ANSI的方式進(jìn)行編譯和運(yùn)行。???
??? 只定義了宏并不能實(shí)現(xiàn)自動(dòng)的轉(zhuǎn)換,他還需要一系列的字符定義支持。???
?? 1. TCHAR???
?? 如果定義了UNICODE宏則TCHAR被定義為wchar_t。???
??? typedef??? wchar_t??? TCHAR;???
??? 否則TCHAR被定義為char???
??? typedef??? char?? TCHAR;???
?? 2.LPTSTR???
如果定義了UNICODE宏則LPTSTR被定義為LPWSTR。(以前一直不知道LPWSTR是什么東東,終于明白了)???
?? typedef??? LPTSTR?? LPWSTR;???
?? 否則TCHAR被定義為char???
?? typedef??? LPTSTR?? LPSTR;??
補(bǔ)充一下:
UTF-8是可以用于真正的流式傳輸?shù)模琔nicode是一種編碼方案???
??? 我的理解是UTF-8是Unicode的一種具體實(shí)現(xiàn)。類似的實(shí)現(xiàn)還有UTF-16等等。
ANSI/Unicode字符和字符串
TChar.h是String.h的修改,用于創(chuàng)建ANSI/Unicode通用字符串。
Unicode字符串的每個(gè)字符都是16位的。
Win9x只支持ANSI;Win2000/XP/2003支持ANSI/Unicode;WinCE只支持Unicode
?????? 附:有部分Unicode函數(shù)也可以在Win9X中使用,但可能會出現(xiàn)意想不到錯(cuò)誤。
wchar_t是Unicode字符的數(shù)據(jù)類型。
所有的Unicode函數(shù)均以wcs開頭,ANSI函數(shù)均以str開頭;ANSI C規(guī)定C運(yùn)行期庫支持ANSI和Unicode
???????????????????????????????? ANSI????????????????????????????????????????????????????????????????????????????? Unicode
?????? char?? *strcat(char?? *,?? const?? char?? *)?????????????????????????? wchar_t?? *wcscat(wchar_t?? *,?? const?? wchar_t?? *)
?????? char?? *strchr(const?? char * , int)?????????????????????????????????? wchar_t??? *wcschr(const?? wchar_t?? * , int)
?????? int?? strcmp(const?? char?? *,??? const?? char?? *)??????????????? int??? wcscmp(const?? wchar_t?? *, const?? wchar_t *)
?????? char *strcpy(char?? *,?? const?? char?? *)?????????????????????????? wchar_t?? *wcscpy(wchar_t??? *,?? const?? wchar_t??? *)
?????? size_t?? strlen(const?? char?? *)??????????????????????????????????????? wchar_t??? wcslen(const?? wchar_t?? *)
L" wash " : 用于將ANSI字符串轉(zhuǎn)換為Unicode字符串;
??????? _TEXT(" wash ")根據(jù)是否定義Unicode或_Unicode進(jìn)行轉(zhuǎn)換。
?????? 附:_Unicode用于C運(yùn)行庫;Unicode用于Windows頭文件。
ANSI/Unicode通用數(shù)據(jù)類型
??????????????????????? Both(ANSI/Unicode)??????????????????? ANSI?????????????????????? Unicode
?????????????????????????????? LPCTSTR???????????????????????????????? LPCSTR?????????????????? LPCWSTR
?????????????????????????????? LPTSTR??????????????????????????????????? LPSTR????????????????????? LPWSTR
?????????????????????????????? PCTSTR?????????????????????????????????? PCSTR????????????????????? PCWSTR
?????????????????????????????? PTSTR????????????????????????????????????? PSTR???????????????????????? PWSTR
?????????????????????????????? TBYTE(TCHAR)????????????????????? CHAR???????????????????????? WCHAR
在設(shè)計(jì)dll時(shí)最好提供ANSI和Unicode函數(shù),ANSI函數(shù)只用于分配內(nèi)存,將字符轉(zhuǎn)換為Unicode字符,然后調(diào)用Unicode函數(shù)。
最好使用操作系統(tǒng)函數(shù),少使用或不實(shí)用C運(yùn)行期函數(shù)
??????? eg:操作系統(tǒng)字符串函數(shù)(shlWApi.h)
??????????????? StrCat(), StrChr(), StrCmp(), StrCpy()等
??????????????? 注意它們區(qū)分大小寫,也區(qū)分ANSI和Unicode版本
??????? 附:ANSI版函數(shù)在原函數(shù)后加大寫字母A
??????????????? Unicode函數(shù)在原函數(shù)后加大寫字母W
成為符合ANSI和Unicode的函數(shù)
??????? ? 將文本串視為字符數(shù)組,而不是c h a r s數(shù)組或字節(jié)數(shù)組。
??????? ? 將通用數(shù)據(jù)類型(如T C H A R和P T S T R)用于文本字符和字符串。
??????? ? 將顯式數(shù)據(jù)類型(如B Y T E和P B Y T E)用于字節(jié)、字節(jié)指針和數(shù)據(jù)緩存。
??????? ? 將T E X T宏用于原義字符和字符串。
??????? ? 修改字符串運(yùn)算問題 。
????????? 如:sizeof(szBuffer) -> sizeof(szBuffer) / sizeof(TCHAR)
????????????????? malloc(charNum) -> malloc(charNum * sizeof(TCHAR))????
對Unicode字符操作的函數(shù)還有:(也有ANSI和Unicode版本)
?????? lstrcat() , lstrcmp() / lstrcmpi()[ 它們在內(nèi)部調(diào)用CompareString() ], lstrcpy(), lstrlen()
?????? 這些是作為宏實(shí)現(xiàn)的。
????????? C運(yùn)行期函數(shù)?????????????????????????????????????? windows函數(shù)
????????????????? tolower()????????????????????????????????? PTSTR?? CharLower(PTSTR?? pszString)
????????????????? toupper()???????????????????????????????? PTSTR?? CharUpper(PTSTR?? pszString)
????????????????? isalpha()????????????????????????????????? BOOL?? IsCharAlpha(TCHAR?? ch)
?????????????????????????????????????????????????????????????????? BOOL?? ISCharAlphaNumeric(TCHAR?? ch)
????????????????? islower()????????????????????????????????? BOOL?? IsCharLower(TCHAR?? ch)
????????????????? isupper()???????????????????????????????? BOOL?? IsCharUpper(TCHAR?? ch)
????????????????? print()?????????????????????????????????????? wsprintf()
?????? 轉(zhuǎn)換Buffer:DWORD?? CharLowerBuffer(PTSTR?? pszString , DWORD cchString)
????????????????????????????? DWORD CharUpperBuffer(PTSTR?? pszString , DWORD?? cchString)
?????? 也可轉(zhuǎn)換單個(gè)字符,如:TCHAR?? cLowerCaseChar = CharLower((PTSTR)szString[0])
確定字符是ANSI或Unicode
??????? BOOL?? IsTextUnicode(
???????????????????? const?? VOID?? * pBuffer,?? //input?? buffer?? to be?? examined
???????????????????? int?? cb,?????????????????????????????? //size of input?? buffer
???????????????????? LPINT?? lpi???????????????????????? //options
??????? )
?????? 附:此函數(shù)在Win9x系統(tǒng)中,沒有實(shí)現(xiàn)代碼,始終返回FALSE
Unicode與ANSI之間的轉(zhuǎn)換
??????? char?? szA[40];
??????? wchar?? szW[40];
??????? // Normal?? sprintf : all?? string?? are?? ANSI
??????? sprintf( szA , " %s " , " ANSI?? str ");
??????? // Convert?? Unicode?? string?? to ANSI
??????? sprintf(?? szA,?? " %S " ,?? L" Unicode?? str ");
??????? // Normal?? swprintf : all string are unicode
??????? swprinf( szW , "%s" , L" Unicode?? str ");
??????? // Convert?? ANSI?? String to Unicode
??????? swprinf( szW, L"%S" , "ANSI str");
??????? int?? MultiByteToWideChar(
????????????? UINT?? uCodePage,?????????????????? //code page,?? 0
????????????? DWORD?? dwFlags,?????????????????? //character-type?? options,?? 0
????????????? PCSTR?? pMultiByte,????????????????? //source?? string?? Addr
????????????? int?? cchMultiByte,?????????????????????? //source?? string?? byte length
????????????? PWSTR?? pWideCharStr,????????? //Dest string?? Addr
????????????? int?? cchWideChar????????????????????? //Dest?? string char?? Nums
???????? )
??????? u C o d e P a g e參數(shù)用于標(biāo)識一個(gè)與多字節(jié)字符串相關(guān)的代碼頁號。d w F l a g s參數(shù)用于設(shè)定另一個(gè)控件,它可以用重音符號之類的區(qū)分標(biāo)記來影響字符。這些標(biāo)志通常并不使用,在d w F l a g s參數(shù)中傳遞0。p M u l t i B y t e S t r參數(shù)用于設(shè)定要轉(zhuǎn)換的字符串, c c h M u l t i B y t e參數(shù)用于指明該字符串的長度(按字節(jié)計(jì)算)。如果為c c h M u l t i B y t e參數(shù)傳遞- 1,那么該函數(shù)用于確定源字符串的長度。轉(zhuǎn)換后產(chǎn)生的U n i c o d e版本字符串將被寫入內(nèi)存中的緩存,其地址由p Wi d e C h a r S t r參數(shù)指定。必須在c c h Wi d e C h a r參數(shù)中設(shè)定該緩存的最大值(以字符為計(jì)量單位)。如果調(diào)用M u l t i B y t e To Wi d e C h a r,給c c h Wi d e C h a r參數(shù)傳遞0,那么該參數(shù)將不執(zhí)行字符串的轉(zhuǎn)換,而是返回為使轉(zhuǎn)換取得成功所需要的緩存的值。
???? 可以通過下列步驟將多字節(jié)字符串轉(zhuǎn)換成U n i c o d e等價(jià)字符串:
???? 1) 調(diào)用M u l t i B y t e To Wi d e C h a r函數(shù),為p Wi d e C h a r S t r參數(shù)傳遞N U L L,為c c h Wi d e C h a r參數(shù)傳遞0。
???? 2) 分配足夠的內(nèi)存塊,用于存放轉(zhuǎn)換后的U n i c o d e字符串。該內(nèi)存塊的大小由前面對M u l t B y t e To Wi d e C h a r的調(diào)用返回。
???? 3) 再次調(diào)用M u l t i B y t e To Wi d e C h a r,這次將緩存的地址作為p Wi d e C h a r S t r參數(shù)來傳遞,并傳遞第一次調(diào)用M u l t i B y t e To Wi d e C h a r時(shí)返回的緩存大小,作為c c h Wi d e c h a r參數(shù)。
???? 4) 使用轉(zhuǎn)換后的字符串。
???? 5) 釋放U n i c o d e字符串占用的內(nèi)存塊。
??? int WideCharToMultiByte(
????????? UINT CodePage,??????????????????????? // code page
????????? DWORD dwFlags,????????????????????? // performance and mapping flags
????????? LPCWSTR lpWideCharStr,????? // wide-character string
????????? int cchWideChar,?????????????????????? // number of chars in string
????????? LPSTR lpMultiByteStr,?????????????? // buffer for new string
????????? int cbMultiByte,?????????????????????????? // size of buffer
????????? LPCSTR lpDefaultChar,??????????? // default for unmappable chars
????????? LPBOOL lpUsedDefaultChar?? // set when default char used
???? )