Unicode,UTF-32,UTF-16,UTF-8

本文介绍了Unicode字符集及其与UTF-32、UTF-16和UTF-8的关系。Unicode包含17个平面,基本平面用于常见字符,辅助平面用于扩展字符。UTF-32将Unicode字符编码为固定4字节,不常用;UTF-16对基本平面字符保持2字节,辅助平面字符通过转换为2个字节表示;UTF-8则根据字符范围编码为1-4字节,是最常用的Unicode编码方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前提说明

二进制,八进制,十进制,十六进制这些都只是对一个数值的书写方式,和一个数值在计算机内存中用多少字节进行存储没有任何关系。
一个数值在计算机中存储时,如果想保证存储经度,且保证存储内存消耗少,那将数值转换为二进制后,消掉所有的高位0,剩下的二进制的位数:小于等于1个字节,那就用1个字节存储;小于等于2个字节,那就用2个字节存储;小于等于3个字节,那就用3个字节存储;小于等于4个字节,那就用4个字节存储。。。
例如:

0x40 => 01000000 消掉高位0 => 1000000 => 位数小于1个字节 => 可以只用1个字节存储
如果我们非要使用4个字节存储 0x40
那使用4个字节存储的 0x40 在内存中的二进制是:00000000 00000000 00000000 01000000 浪费了3个字节内存
所以在内存中存储数值时,应该在保证精度的前提下,尽量消掉所有内存高位的0

Unicode概述

  • 我们通常说的Unicode是一个字符集,在这个字符集中每个字符都有对应的唯一十六进制值。
  • Unicdoe字符集包含了全球所有的字符,所以它的体积较为庞大,如此便分为了17个平面。
  • 17个平面中第一个平面为基本平面(BMP),剩下的16个为辅助平面(SMP)。
  • 基本平面的字符对应十六进制值的区域为0x0000~0xFFFF,辅助平面中的字符对应十六进制值的区域为0x010000~0x10FFFF

查看完整的Unicode字符集(地址1地址2

UTF-32

UTF-32实质是一种重新编码计算的方式,是依附于Unicode字符集的。以Unicode字符集为参考基础,对其中的字符所对应的十六进制值进行重新计算获取一个新的十六进制值。如果我们对Unicode字符集中的所有字符都进行了UTF-32编码,那获得的值组合起来就可以说是一个UTF-32字符集了。

UTF-32的编码方式就是将 Unicode字符集中的字符对应的十六进制变为4个字节存储。
变为4个字节存储的方式就是,在二进制的高位一直添加0,直到满足4个字节为止。
例如:

0x0000   => 00000000 00000000 => 00000000 00000000 00000000 00000000 => 0x00000000
0x1EC0   => 00011110 11000000 => 00000000 00000000 00011110 11000000 => 0x00001EC0
0xFFFF   => 11111111 11111111 => 00000000 00000000 11111111 11111111 => 0x0000FFFF
0x10FFFF => 00010000 11111111 11111111 => 00000000 00010000 11111111 11111111 => 0x0010FFFF

注:Unicdoe字符集中的十六进制值暂时不清楚是几个字节,但是UTF-32编码后,其值必定是4个字节的十六进制,如此UTF-32编码结果在内存中所占空间就过大了,所以通常我们不会去使用,且HTML5明确规定不使用UTF-32进行编码

UTF-16

UTF-16实质是一种重新编码计算的方式,是依附于Unicode字符集的。以Unicode字符集为参考基础,对其中的字符所对应的十六进制值进行重新计算获取一个新的十六进制值。如果我们对Unicode字符集中的所有字符都进行了UTF-16编码,那获得的值组合起来就可以说是一个UTF-16字符集了。

UTF-16的编码方式:

  • Unicode字符集的基本平面中的十六进制,可以直接拿来使用,只要确保是使用2个字节进行存储的就行
  • Unicode字符集的辅助平面中的十六进制(0x010000~0x10FFFF),都是由3个字节去进行存储的,UTF-16的编码方式是将3个字节的十六进制变为两个2个字节的十六进制。转换后的2个字节的十六进制中 第一个十六进制(称为高位H) 在0xD800~0xDBFF范围中, 第二个十六进制(称为低位L) 在0xDC00~0xDFFF范围中

UTF-16在辅助平面中转换公式(公式中的c代表被转换的十六进制):
H = Math.floor((c-0x10000) / 0x400)+0xD800
L = (c - 0x10000) % 0x400 + 0xDC00

例如,转换0x1D306
H = Math.floor((0x1D306 - 0x10000) / 0x400) + 0xD800 = 0xD834
L = (0x1D306 - 0x10000) % 0x400 + 0xDC00 = 0xDF06
0x1D306进行UTF-16编码后的结果就是\u0xD834\u0xDF06

UTF-16的编码方式,对于基本平面没什么影响,依然都是使用2个字节进行存储的十六进制值,而辅助平面在Unicode中都是使用3到4个字节进行存储十六进制值的,所以UTF-16编码需要将使用3到4个字节进行存储的十六进制值进行转换,转化为2个字节存储的十六进制值,所以上面将 3到4个字节进行存储十六进制值 转换为了 两个2个字节进行存储十六进制值

UTF-8

UTF-8实质是一种重新编码计算的方式,是依附于Unicode字符集的。以Unicode字符集为参考基础,对其中的字符所对应的十六进制值进行重新计算获取一个新的十六进制值。如果我们对Unicode字符集中的所有字符都进行了UTF-8编码,那获得的值组合起来就可以说是一个UTF-8字符集了。

UTF-8的编码方式(最终是要将Unicode中的十六进制值转换为由 1个 或者 2个 或者 3个 或者 4个 字节存储的十六进制值):

Unicode十六进制(高位0都去掉)Unicode二进制(高位0都去掉)UTF-8二进制(其中的 x 由前面的Unicode二进制值来决定)
0x0 ~ 0x7F0 ~ 11111110xxxxxxx
0x80 ~ 0x7FF10000000 ~ 111 11111111110xxxxx 10xxxxxx
0x800 ~ 0xFFFF1000 00000000 ~ 11111111 111111111110xxxx 10xxxxxx 10xxxxxx
0x10000 ~ 0x10FFFF1 00000000 00000000 ~ 10000 11111111 1111111111110xxx 10xxxxxx 10xxxxxx 10xxxxxx

先确定Unicode的十六进制值所在区域范围,找到对应范围的UTF-8二进制编码格式(就是上表的UTF-8二进制那一列),然后将Unicode的十六进制值转为二进制值,在将二进制值填写进对应的UTF-8二进制编码格式中(填写方式,从最后一个二进制位开始,依次从后向前填入格式中的x,多出的x填0)。

编码示例,字符 @
字符 @ 的Unicode十六进制是0x40,Unicode二进制是1000000,对应的UTF-8二进制格式是0xxxxxxx
根据填写方式进行填写的最终结果:
这里写图片描述 二进制结果转为十六进制0x0040\u0040

编码示例,字符 ˃
字符 ˃ 的Unicode十六进制是0x2C3,Unicode二进制是10 11000011,对应的UTF-8二进制格式是110xxxxx 10xxxxxx
根据填写方式进行填写的最终结果:
这里写图片描述 二进制结果转为十六进制0xCB83\uCB83


参考博客:

  1. http://www.admin10000.com/document/5643.html
  2. https://www.jb51.net/article/59178.htm
  3. https://blog.youkuaiyun.com/tuzhao/article/details/52046096
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值