问:UTF-8和UTF-16有什么区别,和Unicode又有什么关系?

207 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第17天

UTF-8和UTF-16有什么区别,和Unicode又有什么关系?

Unicode

Unicode又称单一码,万国码,是我们计算机领域的行业标准,它为我们扩展了字符集,容纳了所有的语言字符,解决了传统字符编码集表示字符量少的问题

UTF和Unicode的关系

UFT是 Unicode Transformation Format 的缩写,意为Unicode转换格式,Unicode中的编码可以理解为数字,而数字又有多种进制表现,在计算机内的东西最终必然要用二进制来存储,但二进制又过长,随着Unicode编码不断增大,八位二进制数(一个字节的长度)往往已经不够使用,于是就需要我们的UTF-8和UTF-16来规范格式

UTF-8

从 -8 可以简单猜出,它用八个单字节为一个单位(单位名叫码元),来表示编码,当八个单字节(一个字节)不够用了怎么办?再来八个!就这样通过扩展长度来满足表示大编码的字符。

但问题就出来了,计算机怎么知道我们为表示单个字符用了几个字节呢?它为什么不会把它拆开转换呢?

为解决这个问题,UTF-8编码的开头有标识位:

  • 如果读取到的第一个字节中二进制是以0打头,就说明它只有这一个字符:0XXXXXXX

  • 如果读取到的第一个字节中二进制是以110开头,就说明这个字符通过双字节的方式来表示,同样的,第二个字节的二进制表示也有标识位,是以10开头:110XXXXX 10XXXXXX

  • 以此类推,如果是以三个字节表示编码:1110XXXX 110XXXXX 10XXXXXX

UTF-16

我们知道了UTF-8的表示方式,UTF-16也就大致明白了,通过16个单字节为一个码元来表示字符,而这16个单字节,UTF-16的2个字节在计算机中存储分为大端存储(big ending)和小端存储(little ending)

  • little ending:将低位字节放在字符起始位置存储,比如0x1234,我将低位的0x34存储在起始的存储单元,将0x12存储在后续的存储单元
  • big ending:将高位字节放在字符起始位置存储,还比如0x1234,将高位0x12存储在起始的存储单元,将0x34存储在后续的存储单元中

不同的存储方式对应的解析方式也不同,比如java存储采用big ending,c/c++ 在x86平台下采取little ending,当两个程序互通时,就需要转换字节序了

UTF-8和UTF-16对比

UTF-16的好处就在于,如果表示通过两个字节才能表示的字符,使用UTF-16编码时,不需要标识符,比UTF-8效率高,但表示类似英文字母时,即使用不到16个单字节,UTF-16编码也会占用16个单字节的存储空间,又比UTF-8效率更低,在表示三个字节大小的字符时也同理,即使只需要3个字节,UTF-16也会申请4个字节来存储,因此两者各有所长,主要看用户的使用以哪种字符为主。