windows把字符串分成兩類,,UNICODE字符串和基于code page的ANSI字符串。UNICDOE字符串使用UTF-16LE編碼方式(占2字節(jié),,其值與UNICODE編碼真值一致,,暫不考慮位于BMP之外的情況)。ANSI字符串使用多字節(jié)編碼方式,,以簡(jiǎn)體中文GBK為例(code page 936),,ASCII碼使用1字節(jié),中文使用2字節(jié),,使用leadbyte來區(qū)分兩者,。
在C/C++程序(VS2010)里,UNICODE字符串對(duì)應(yīng)wchar_t,,ANSI字符串對(duì)應(yīng)char,。比如字符串 L"漢" 的二進(jìn)制值是0x6c49,與UNICODE編碼真值一致,。字符串 "漢" 的二進(jìn)制值是0xba,0xba,,與GBK編碼真值一致。 在字符串操作中,,有時(shí)需要在UNICODE字符串和ANSI字符串之間進(jìn)行轉(zhuǎn)換。下面以輸出一個(gè)字符串到文本文件為例,,講講這個(gè)轉(zhuǎn)換過程(輸出到console稍微有點(diǎn)特殊,,后面討論)。根據(jù)輸出操作中源和目標(biāo)的字符串模式,,可以分成以下4種情況: 情況1,,源為ANSI模式,目標(biāo)為ANSI模式,。 這是我們最常用的情況,,源和目標(biāo)模式一致,無需轉(zhuǎn)換,。 [cpp] view plaincopy
在上面的代碼里,,源是ANSI字符串"abc漢字",以默認(rèn)方式打開的目標(biāo)fp也是ANSI模式,。 情況2,,源為ANSI模式,,目標(biāo)為UNICODE模式。 這種情況是不允許的,,從微軟代碼的注釋來看,,是為了防止ANSI系列函數(shù)操作UNICODE文件。 情況3,,源為UNICODE模式,,目標(biāo)為ANSI模式。 為了使源為UNICODE模式,,我們只能使用wchar_t字符串,,比如下面的代碼: [cpp] view plaincopy
源是UNICODE字符串(UTF-16LE編碼方式),以默認(rèn)方式打開的目標(biāo)fp是ANSI模式,。 通過調(diào)用wctomb函數(shù)把UNICODE字符串轉(zhuǎn)成基于code page的ANSI字符串,,這也是目標(biāo)fp可以接受的字符串。 wctomb函數(shù)的行為是跟locale相關(guān)的,,如果是c locale,,它會(huì)逐個(gè)判斷wchar_t,如果值大于255,,則是出錯(cuò),,否則強(qiáng)制轉(zhuǎn)換成char;如果不是c locale,,比如chinese locale,,它會(huì)以該locale對(duì)應(yīng)的code page(比如936)為參數(shù)調(diào)用WideCharToMultiByte進(jìn)行轉(zhuǎn)換。 情況4,,源為UNICODE模式,,目標(biāo)為UNICODE模式。 做為源使用的wchar_t字符串,,其編碼模式是UTF-16LE,。做為目標(biāo),則有兩種選擇,,UTF-16LE和UTF-8,。 [cpp] view plaincopy
如果目標(biāo)是UTF-16LE編碼模式,則與源是一致的,,無需轉(zhuǎn)換,。如果目標(biāo)是UTF-8編碼模式,則需要以UTF-8 code page為參數(shù)調(diào)用WideCharToMultiByte進(jìn)行轉(zhuǎn)換,。
上面是操作普通文本文件,,接下來是操作console,同樣可以分成4種情況: 情況1,源為ANSI模式,,目標(biāo)為ANSI模式,。 雖然源和目標(biāo)模式一致,但還需要根據(jù)locale進(jìn)行不同處理,。如果是c locale,,則無需轉(zhuǎn)換,直接寫入(用WriteFile寫到console對(duì)應(yīng)的句柄),。否則,,需要分兩步處理。第一步,,調(diào)用mbtowc將源字符串(ANSI模式)轉(zhuǎn)成臨時(shí)的UNICODE字符串(UTF-16LE),。第二步,以console code page為參數(shù)調(diào)用WideCharToMultiByte將臨時(shí)的UNICODE字符串轉(zhuǎn)成目標(biāo)字符串(ANSI模式),,再寫入(WriteFile),。 這里需要注意,雖然都是ANSI模式,,但源字符串是基于相應(yīng)locale的code page,,目標(biāo)字符串是基于console的code page(這兩個(gè)code page往往是一樣的)。 mbtowc的行為是locale相關(guān)的,,如果是c locale,,則將char強(qiáng)制轉(zhuǎn)成wchar_t(在上面的第一步中,顯然不會(huì)遇到這種情況),。否則,,以相應(yīng)locale的code page為參數(shù)調(diào)用MultiByteToWideChar進(jìn)行轉(zhuǎn)換,將ANSI字符串轉(zhuǎn)成UNICODE字符串(UTF-16LE),。 情況2,,源為ANSI模式,目標(biāo)為UNICODE模式,。 這種情況也是不允許的,。 情況3,源為UNICDOE模式,,目標(biāo)為ANSI模式。 這里的源字符串也只能是UTF-16LE編碼方式,。如果是c locale,,則逐個(gè)判斷wchar_t,值大于255是出錯(cuò),,否則強(qiáng)制轉(zhuǎn)成char寫入(WriteFile),。如果不是c locale,這是最復(fù)雜的一種情況,需要經(jīng)過三次轉(zhuǎn)換: 首先,,以相應(yīng)locale的code page為參數(shù)調(diào)用WideCharToMultiByte將源字符(UNICODE模式)串轉(zhuǎn)成臨時(shí)的ANSI字符串,。 接著,調(diào)用mbtowc將臨時(shí)的ANSI字符串轉(zhuǎn)成臨時(shí)的UNICODE字符串(這個(gè)字符串其實(shí)跟源字符串是一致的,,但代碼的流程就是這樣走的),。 最后,以console code page為參數(shù)調(diào)用WideCharToMultiByte將臨時(shí)的UNICODE字符串轉(zhuǎn)成目標(biāo)字符串(ANSI模式),,再寫入(WriteFile),。最后這兩步與情況1的兩步是一樣的。 情況4,,源為UNICODE模式,,目標(biāo)為UNICODE模式。 做為源使用的wchar_t字符串,,其編碼模式是UTF-16LE,。做為目標(biāo),則有兩種編碼模式,,UTF-16LE和UTF-8,。無需區(qū)分這兩種情況,windows已經(jīng)幫我們處理好了,,直接調(diào)用WriteConsoleW寫入,。 [cpp] view plaincopy
|
|