簡單幾句話總結Unicode,UTF-8和UTF-16

概念

先說一說基本的概念,這包括什麼是Unicode,什麼是UTF-8,什麼是UTF-16。windows

Unicode,UTF-8,UTF-16完整的說明請參考Wiki(UnicodeUTF-8UTF-16)。用比較簡單的話來講就是,Unicode定義了全部能夠用來表示字符的數值集合(稱之爲Code Point)。UTF-8和UTF-16等UTF標準定義了這些數值和字符的映射關係。網絡

UTF-8

優點

UTF-8最大的優點是,沒有字節序的概念。因此特別適合用於字符串的網絡數據傳輸,不用考慮大小端問題。對於非英文網頁(對於咱們而言,簡單說東亞文字網頁),可以避免各類亂碼問題。網站

劣勢

本地字符串處理過程當中,若是使用UTF-8,對於英文字符的處理沒有太大的問題。一個char變量表示一個英文字符。可是對於中文等遠東字符集來講,就比較坑爹了。char str[]; str[0]並不能完整表示一個漢字。UTF-8編碼格式下,一個漢字須要至少3個char才能表示。這對於經過下標來操做字符串的操做來講是很是痛苦的一件事情。網絡傳輸協議

另外,一個漢字須要至少3個char來表示,也讓漢字在網絡傳輸上存在劣勢,佔用太多流量(可是若是啓用了壓縮,實際上差異並不大。而且如今不少中文網站都默認將編碼從GBK改爲了UTF-8)。編碼

UTF-16

優點

UTF-16 LE是windows上默認的Unicode編碼方式,使用wchar_t表示。全部wchar_t *類型的字符串(包括硬編碼在.h/.cpp裏的字符串字面值),VC都自動採用UTF-16的編碼(字符串字面值,literal string,存在不少坑。特別是char *類型的字面值,最終內存使用何種編碼方式徹底取決於當前文件的編碼方式。也就是說當前文件若是是GBK編碼的,那麼文件裏char * str = "中午",str指向的內存字符串二進制是使用GBK編碼的。若是文件編碼是UTF-8,那麼內存是使用UTF-8編碼。因此爲何一直要強調字符串應該放在資源文件裏,而不是硬編碼在.h/.cpp文件裏!)。code

UTF-16另一個優點就是經常使用字符均可以使用兩個個字節表示,也就是一個wchar_t(這裏指Windows平臺)。因此,在Windows平臺上,特別適合使用wchar_t來做爲字符串的存儲基類型。一個wchar_t表示一個字符。操做使用很是方便。排序

劣勢

沒有統一的表示UTF-16編碼的字符類型。C++98/03裏對wchar_t的定義是很是寬泛的。這致使在Windows平臺上,wchar_t是2字節的;在Unix-like系統上是4字節的。代碼移植上,可能會遇到挑戰(我沒移植過,因此不肯定會有什麼難度,以及難度有多大)。ip

即便最新的C++11裏已經定義除了char16_t表示UTF-16,MS的VS2013還不支持char16_t。因此目前使用char16_t還不具移植性。內存

據我瞭解,UTF-16編碼和GBK編碼相比,還存在一個排序的劣勢。也就是說,若是要按照漢語拼音的字母順序對漢字進行排序,GBK會獲得正確的結果,而UTF-16就不行(暫時我還沒這種需求,因此我沒驗證過,不過好像我立刻就要與到這種需求了,到時候我再驗證下)。資源

UTF-16編碼字符串的網絡傳輸,要考慮大小端的問題。另外網絡傳輸中若是一個字節信息丟失,剩下的字符串都沒法正確解析。通通亂碼。

另外,UTF-16並非定長類型。因此仍是存在生僻字使用4個字節編碼而不是2個字節(可是Windows有例外。在Windows(NT內核)平臺,從MSDN的各類表述來看,彷佛一個wchar_t就是一個字符。更多關於Windows平臺字符編碼的問題參考知乎回答和相關評論)。

UTF-32

優點

這個優點就明顯了,全部字符都是4字節,fix-length。一個wchar_t(Unix-like系統上)表示一個字符。

劣勢

對於以英文爲主的字符串來講,空間消耗大。

面臨和上面UTF-16同樣的問題。一致性,排序,網絡傳輸,數據丟失後沒法恢復。char32_t VS2013還不支持(甚至VS 14 CPT也沒打算支持)。

總結

UTF-8最適合用來做爲字符串網絡傳輸的編碼格式。UTF-16最適合看成本地字符串編碼格式。若是定義好了網絡傳輸協議,那麼UTF-16也很是合適看成網絡字符串傳輸的編碼格式,特別是中文等遠東地區字符集。比起UTF-8來講,節省一點點流量。UTF-32沒什麼特殊癖好或者需求的話,暫時還用不上。

最後,推薦一篇文章:UTF-8 Everywhere

我我的以爲最佳實踐應該是:

  1. Linux上使用char,採用UTF-8編碼。
  2. 網絡傳輸使用UTF-8編碼。
  3. Windows上使用wchar_t / char16_t,採用UTF-16編碼。將收到的網絡數據統一從UTF-8轉碼到UTF-16。在Windows上應該銘記沒有char / std::string這種類型的字符/字符串,只有wchar_t / char16_t / std::wstring / std::u16string。
相關文章
相關標籤/搜索