常见的字符编码UTF-8、UTF-16、UTF-32

时间:2024-04-09 15:05:12

字符集

字符集为每个字符分配了一个唯一的编号,通过这个编号就能找到对应的字符。在编程过程中我们经常会使用字符,而使用字符的前提就是把字符放入内存中,毫无疑问,放入内存中的仅仅是字符的编号,而不是真正的字符实体。

如何才能将字符编号放入内存中呢?

对于ASCII字符集,这很容易。ASCII 总共包含 128 个字符,用 7
个比特位(Bit)恰好能够存储,不过考虑到计算机一般把字节(Byte)作为基本单元,为了操作方便,我们不妨用一个字节(也就是 8
个比特位)来存储 ASCII。这样虽然浪费了一个比特位,但是读写效率提高了。

但是对于 Unicode,问题就没有这么简单了。Unicode
目前已经包含了上百万的字符,位置靠前的字符用一个字节就能存储,位置靠后的字符用三个字节才能存储。我们可以为所有字符都分配三个字节的内存,也可以为编号小的字符分配一个字节或者两个字节的内存,而为编号大的字符分配三个字节的内存。

注:Unicode和ASCII 为字符集
注:字符集和字符编码不是一个概念,字符集定义了文字和二进制的对应关系,为字符分配了唯一的编号,而字符编码规定了如何将文字的编号存储到内存中。有的字符集在制定时就考虑到了编码的问题,是和编码结合在一起的;有的字符集只管制定字符的编号,至于怎么编码,是其他人的事情。

上面的问题有两个解决方案

1.为每个字符分配固定长度的内存
2.为每个字符分配尽量少的内存

Unicode 到底使用哪种编码方案???

Unicode 可以使用的编码有三种,分别是:

  • UFT-8:一种变长的编码方案,使用 1~6 个字节来存储;
  • UFT-32:一种固定长度的编码方案,不管字符编号大小,始终使用 4 个字节来存储;
  • UTF-16:介于 UTF-8 和 UTF-32 之间,使用 2 个或者 4 个字节来存储,长度既固定又可变。
    注:UTF 是 Unicode Transformation Format 的缩写,意思是“Unicode转换格式”,后面的数字表明至少使用多少个比特位(Bit)来存储字符。

下面我们介绍着这几种编码方式

UTF-8

UTF-8 的编码规则很简单:如果只有一个字节,那么最高的比特位为 0;如果有多个字节,那么第一个字节从最高位开始,连续有几个比特位的值为 1,就使用几个字节编码,剩下的字节均以 10 开头。
具体的表现形式为:

  • 0xxxxxxx:单字节编码形式,这和 ASCII 编码完全一样,因此 UTF-8 是兼容 ASCII 的;
  • 110xxxxx 10xxxxxx:双字节编码形式;
  • 1110xxxx 10xxxxxx 10xxxxxx:三字节编码形式;
  • 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx:四字节编码形式。
    注:xxx 就用来存储 Unicode 中的字符编号。

UTF-32

UTF-32 是固定长度的编码,始终占用 4 个字节,足以容纳所有的 Unicode 字符,所以直接存储 Unicode 编号即可,不需要任何编码转换。浪费了空间,提高了效率。

UTF-16

UFT-16 比较奇葩,它使用 2 个或者 4 个字节来存储。
对于 Unicode 编号范围在 0 ~ FFFF 之间的字符,UTF-16 使用两个字节存储,并且直接存储 Unicode 编号,不用进行编码转换,这跟 UTF-32 非常类似。
对于 Unicode 编号范围在 10000~10FFFF 之间的字符,UTF-16 使用四个字节存储,具体来说就是:将字符编号的所有比特位分成两部分,较高的一些比特位用一个值介于 D800~DBFF 之间的双字节存储,较低的一些比特位(剩下的比特位)用一个值介于 DC00~DFFF 之间的双字节存储。

注:只有 UTF-8 兼容 ASCII,UTF-32 和 UTF-16 都不兼容 ASCII,因为它们没有单字节编码。

GB2312、Shift-JIS 等国家(地区)字符集怎么编码

GB2312、GBK、Shift-JIS 等特定国家的字符集都是在 ASCII 的基础上发展起来的,它们都兼容 ASCII,所以只能采用变长的编码方案:用一个字节存储 ASCII 字符,用多个字节存储本国字符。

以 GB2312 为例,该字符集收录的字符较少,所以使用 1~2 个字节编码。

  • 对于 ASCII 字符,使用一个字节存储,并且该字节的最高位是 0;
  • 对于中国的字符,使用两个字节存储,并且规定每个字节的最高位都是 1。
    由于单字节和双字节的最高位不一样,所以很容易区分一个字符到底用了几个字节。

宽字符和窄字符(多字节字符)

有的编码方式采用 1~n 个字节存储,是变长的,例如 UTF-8、GB2312、GBK 等;如果一个字符使用了这种编码方式,我们就将它称为多字节字符,或者窄字符。

有的编码方式是固定长度的,不管字符编号大小,始终采用 n 个字节存储,例如 UTF-32、UTF-16 等;如果一个字符使用了这种编码方式,我们就将它称为宽字符。

Unicode 字符集可以使用窄字符的方式存储,也可以使用宽字符的方式存储;GB2312、GBK、Shift-JIS 等国家编码一般都使用窄字符的方式存储;ASCII 只有一个字节,无所谓窄字符和宽字符。

本文摘自严长生博客







我的真正身份是改变社会风气,风靡万千少女,提高青年人内涵,刺激软件市场,玉树临风的搬砖工?钢丝球君,英文名字叫Tom Siebel

微信扫码?可以进行技术交流,欢迎提问!!!
常见的字符编码UTF-8、UTF-16、UTF-32
可在问题下面输入‘微信号’,拉你进微信技术交流群