UTF-8 UTF-16 UTF-32 比较

news/2024/7/16 6:16:57

优点

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 编码应用更广泛? 参与回答: 林建入- 回答


http://www.niftyadmin.cn/n/3538189.html

相关文章

网站logo

2019独角兽企业重金招聘Python工程师标准>>> 网站logo即打开首页时浏览器所展示的网站标志性的图片&#xff1a; 1、ico图片 2、页面<head></head>加入如下代码&#xff0c;一般将图片和首页文件放到同一路径下。 <link rel"shortcut icon&qu…

pytest 失败用例重试

https://www.cnblogs.com/jinzhuduoduo/articles/7017405.html http://www.lxway.com/445949491.htm https://www.cnblogs.com/feiyi211/p/6625841.html 转载于:https://www.cnblogs.com/dieyaxianju/p/8179183.html

【论文精读3】20WWW Structural Deep Clustering Network (SDCN网络图聚类)

参考好文&#xff1a; 图神经网络时代的深度聚类 - 知乎 (zhihu.com) 几篇文献讲解。 深度聚类算法研究综述(A Survey of Deep Clustering Algorithms) - 凯鲁嘎吉 - 博客园 (cnblogs.com) 深度学习聚类大总结包含公式。 【石川 | 北京邮电大学计算机学院教授】图神经网络…

oracle定时器执行一遍就不执行或本就不执行

转&#xff1a;http://blog.csdn.net/qq_23311211/article/details/76283689 以sqlplus/ assysdba进入sql命令模式&#xff0c;使用sql&#xff1a;select value from v$parameter where name like %job_queue_processes% &#xff0c; 看查询结果是否为0&#xff0c;若是或者数…

【深度学习6】对比学习(Contrastive Learning)入门

主要内容&#xff1a; 1. 何为对比 2. 如何构造正负样本 3. 对比学习loss 4. 对比学习loss代码 1. 何为对比 「对比学习」属于无监督学习的一种&#xff0c;即给一堆数据&#xff0c;没有标签&#xff0c;自己学习出一种特征表示。 我们知道的无监督方法有聚类(迭代地更…

Android中的消息机制

提到Android中的消息机制&#xff0c;首先想到的必定是Handler,Looper和MesageQueue&#xff0c;我们在开发中接触到的最多的就是Handler&#xff0c;至于Looper和MessageQueue我们是知道的&#xff0c;但是并不会对其进行操作&#xff0c;最多的用法就是在子线程请求数据&…

asp设置cookies的过期时间

2019独角兽企业重金招聘Python工程师标准>>> 在ASP技术中&#xff0c;Cookie是Response的唯一的一个集合&#xff0c;是Web服务器在用户的浏览器中用来代表用户的令牌。当同一浏览器又一次请求同一Cookie设定的页面时&#xff0c;它将从用户端把上一次从Web服务器中…

【云原生】安装Docker、拉取pytorch镜像、拷贝程序到容器

1、安装docker 每台机器上执行下面的命令 # 关闭防火墙 systemctl stop firewalld systemctl disable firewalld# 关闭selinux # 永久关闭 sed -i s/enforcing/disabled/ /etc/selinux/config # 临时关闭 setenforce 0 # 关闭swap # 临时 swapoff -a # 永久关闭 sed -ri …