概念先說一說基本的概念,這包括什么是Unicode,什么是UTF-8,什么是UTF-16。 Unicode,UTF-8,UTF-16完整的說明請參考Wiki(Unicode,UTF-8,UTF-16)。用比較簡單的話來說就是,Unicode定義了所有可以用來表示字符的數(shù)值集合(稱之為Code Point)。UTF-8和UTF-16等UTF標準定義了這些數(shù)值和字符的映射關(guān)系。 UTF-8優(yōu)勢UTF-8最大的優(yōu)勢是,沒有字節(jié)序的概念。所以特別適合用于字符串的網(wǎng)絡數(shù)據(jù)傳輸,不用考慮大小端問題。對于非英文網(wǎng)頁(對于我們而言,簡單說東亞文字網(wǎng)頁),能夠避免各種亂碼問題。 劣勢本地字符串處理過程中,如果使用UTF-8,對于英文字符的處理沒有太大的問題。一個char變量表示一個英文字符。但是對于中文等遠東字符集來說,就比較坑爹了。char str[]; str[0]并不能完整表示一個漢字。UTF-8編碼格式下,一個漢字需要至少3個char才能表示。這對于通過下標來操作字符串的操作來說是非常痛苦的一件事情。 另外,一個漢字需要至少3個char來表示,也讓漢字在網(wǎng)絡傳輸上存在劣勢,占用太多流量(但是如果啟用了壓縮,實際上差別并不大。并且現(xiàn)在很多中文網(wǎng)站都默認將編碼從GBK改成了UTF-8)。 UTF-16優(yōu)勢UTF-16 LE是windows上默認的Unicode編碼方式,使用wchar_t表示。所有wchar_t *類型的字符串(包括硬編碼在.h/.cpp里的字符串字面值),VC都自動采用UTF-16的編碼(字符串字面值,literal string,存在很多坑。特別是char *類型的字面值,最終內(nèi)存使用何種編碼方式完全取決于當前文件的編碼方式。也就是說當前文件如果是GBK編碼的,那么文件里char * str = '中午',str指向的內(nèi)存字符串二進制是使用GBK編碼的。如果文件編碼是UTF-8,那么內(nèi)存是使用UTF-8編碼。所以為什么一直要強調(diào)字符串應該放在資源文件里,而不是硬編碼在.h/.cpp文件里!)。 UTF-16另外一個優(yōu)勢就是常用字符都可以使用兩個個字節(jié)表示,也就是一個wchar_t(這里指Windows平臺)。所以,在Windows平臺上,特別適合使用wchar_t來作為字符串的存儲基類型。一個wchar_t表示一個字符。操作使用非常方便。 劣勢沒有統(tǒng)一的表示UTF-16編碼的字符類型。C++98/03里對wchar_t的定義是非常寬泛的。這導致在Windows平臺上,wchar_t是2字節(jié)的;在Unix-like系統(tǒng)上是4字節(jié)的。代碼移植上,可能會遇到挑戰(zhàn)(我沒移植過,所以不確定會有什么難度,以及難度有多大)。 即使最新的C++11里已經(jīng)定義除了char16_t表示UTF-16,MS的VS2013還不支持char16_t。所以目前使用char16_t還不具移植性。 據(jù)我了解,UTF-16編碼和GBK編碼相比,還存在一個排序的劣勢。也就是說,如果要按照漢語拼音的字母順序?qū)h字進行排序,GBK會得到正確的結(jié)果,而UTF-16就不行(暫時我還沒這種需求,所以我沒驗證過,不過好像我馬上就要與到這種需求了,到時候我再驗證下)。 UTF-16編碼字符串的網(wǎng)絡傳輸,要考慮大小端的問題。另外網(wǎng)絡傳輸中如果一個字節(jié)信息丟失,剩下的字符串都無法正確解析。統(tǒng)統(tǒng)亂碼。 另外,UTF-16并不是定長類型。所以還是存在生僻字使用4個字節(jié)編碼而不是2個字節(jié)(但是Windows有例外。在Windows(NT內(nèi)核)平臺,從MSDN的各種表述來看,似乎一個wchar_t就是一個字符。更多關(guān)于Windows平臺字符編碼的問題參考知乎回答和相關(guān)評論)。 UTF-32優(yōu)勢這個優(yōu)勢就明顯了,所有字符都是4字節(jié),fix-length。一個wchar_t(Unix-like系統(tǒng)上)表示一個字符。 劣勢對于以英文為主的字符串來說,空間消耗大。 面臨和上面UTF-16一樣的問題。一致性,排序,網(wǎng)絡傳輸,數(shù)據(jù)丟失后無法恢復。char32_t VS2013還不支持(甚至VS 14 CPT也沒打算支持)。 總結(jié)UTF-8最適合用來作為字符串網(wǎng)絡傳輸?shù)木幋a格式。UTF-16最適合當作本地字符串編碼格式。如果定義好了網(wǎng)絡傳輸協(xié)議,那么UTF-16也非常合適當作網(wǎng)絡字符串傳輸?shù)木幋a格式,特別是中文等遠東地區(qū)字符集。比起UTF-8來說,節(jié)省一點點流量。UTF-32沒什么特殊癖好或者需求的話,暫時還用不上。 最后,推薦一篇文章:UTF-8 Everywhere。 我個人覺得最佳實踐應該是:
|
|