简单几句话总结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。
相关文章
相关标签/搜索