UTF-8 UTF-16 UTF-32 比较

优点

UTF-8

  1. 兼容 ASCII
  2. 能适应许多 C 库中的 \0 结尾惯例
  3. 没有字节序问题
  4. 良好的多语种支持(相对 GBK 等跟语种绑定的编码方式)
  5. 以英文和西文符号比较多的场景下(例如 HTML/XML),编码较短
  6. 由于是变长,字符空间足够大,未来 Unicode 新标准收录更多字符,UTF-8 也能妥妥的兼容,因此不会再出现 UTF-16 那样的尴尬
  7. 不存在大小端字节序问题,信息交换时非常便捷
  8. 容错性高,局部的字节错误(丢失、增加、改变)不会导致连锁性的错误,因为 UTF-8 的字符边界很容易检测出来,这是一个巨大的优点(正是为了实现这一点,咱们中日韩人民不得不忍受 3 字节 1 个字符的苦日子)

UTF-16(应该不算优点)

  1. 最流行的操作系统和 UI framework 的内部字符串表达都是 UTF-16
  • Windows API 的 Wide Char 表达是 UTF-16: Unicode (Windows), L"" 表示是转换为 wide char。
  • Cocoa 的 NSString 和 Core Foundation 的 CFString 内部表达都是 UTF-16,所以其实 OS X 和 iOS 内部处理都用的是 UTF-16。
  • Java String 的内部表达是 UTF-16,所以大量跨平台程序和 Android 程序其实内部也在用 UTF-16。
  1. 在计算字符串长度、执行索引操作时速度很快。

注:但是UTF-16也是变长的,Unicode扩展到9万多以后,也要通过变长来支持了。 具体原因参照知乎回答: 编程语言的字符编码选择UTF-8和UTF-16的优缺点?

UTF-32

  1. 定长编码,utf32 表示任何字符都用 4 字节,读到内存中是个均匀的整形数组,于是我们可以很方便地随机访问任何一个字符
  2. 由于是定长,索引比变长的要快,你想访问一个字符串中的第 n 个字符,utf32 直接偏移 n 个整形距离即可,utf8 得从第一个字节一个字一个字地往后蹦,非常蛋疼。

补充: UTF 32 也不想理想中那么方便索引,主要是 emoji 的锅,举两个例子:一、Emoji 里面的国旗其实由两个字符组成,称为 region indicator,每个字符是一个 region indicator symbol letter,从 A 到 Z,U+1F1E6 到 U+1F1FF。比如说法国国旗就是用 FR 的对应 region indicator symbol letter 来表示的。Swift 的 String 自称有较好的 Unicode 支持,但对这样的字符的长度目前给的还是 2(Unicode 8.0 标准),而实际上 Unicode 9.0 已经要求把它们看作一个字符了。二、为了政治正确,人们引入了带肤色的 emoji 表情,它们是由普通表情和一个代表颜色的 emoji 字符组成。于是乎,如果写编辑器的话,不管怎么样都要 O(n) 来计算可见字符的长度的(这还没有考虑韩语那种三个字符叠成一个字符的情况),所以前端们很可怜的。 参见 刘闽晟 回答,链接

缺点

UTF-8

  1. 文化上的不平衡——对于欧美地区一些以英语为母语的国家 UTF-8 简直是太棒了,因为它和 ASCII 一样,一个字符只占一个字节,没有任何额外的存储负担;但是对于中日韩等国家来说,UTF-8 实在是太冗余,一个字符竟然要占用 3 个字节,存储和传输的效率不但没有提升,反而下降了。所以欧美人民常常毫不犹豫的采用 UTF-8,而我们却老是要犹豫一会儿。
  2. 变长字节表示带来的效率问题——大家对 UTF-8 疑虑重重的一个问题就是在于其因为是变长字节表示,因此无论是计算字符数,还是执行索引操作效率都不高。为了解决这个问题,常常会考虑把 UTF-8 先转换为 UTF-16 或者 UTF-32 后再操作,操作完毕后再转换回去。而这显然是一种性能负担。

UTF-16

  1. UTF-16 能表示的字符数有 6 万多,看起来很多,但是实际上目前 Unicode 5.0 收录的字符已经达到 99024 个字符,早已超过 UTF-16 的存储范围;这直接导致 UTF-16 地位颇为尴尬——如果谁还在想着只要使用 UTF-16 就可以高枕无忧的话,恐怕要失望了。
  2. UTF-16 存在大小端字节序问题,这个问题在进行信息交换时特别突出——如果字节序未协商好,将导致乱码;如果协商好,但是双方一个采用大端一个采用小端,则必然有一方要进行大小端转换,性能损失不可避免(大小端问题其实不像看起来那么简单,有时会涉及硬件、操作系统、上层软件多个层次,可能会进行多次转换)。
  3. 另外,容错性低有时候也是一大问题——局部的字节错误,特别是丢失或增加可能导致所有后续字符全部错乱,错乱后要想恢复,可能很简单,也可能会非常困难。(这一点在日常生活里大家感觉似乎无关紧要,但是在很多特殊环境下却是巨大的缺陷)。

该如何选择

简要回答: UTF-8,用于存储及传输 UTF-32,用于程序内存中

原因:

  • UTF-8灵活,在互联网通信中被编码影响小,兼容性强。
  • UTF-32定长,在内存中程序处理优秀,查询快。

因为无论是 UTF-8 和 UTF-16/32 都各有优缺点,因此选择的时候应当立足于实际的应用场景。例如在我的习惯中,存储在磁盘上或进行网络交换时都会采用 UTF-8,而在程序内部进行处理时则转换为 UTF-16/32。对于大多数简单的程序来说,这样做既可以保证信息交换时容易实现相互兼容,同时在内部处理时会比较简单,性能也还算不错。(基本上只要你的程序不是 I/O 密集型的都可以这么干,当然这只是我粗浅的认识范围内的经验,很可能会被无情的反驳)。

整理自: 知乎 - 为什么 UTF-8 编码比 UTF-16 编码应用更广泛? 参与回答: 林建入- 回答

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值