Unicode的UTF-8 UTF-16

Unicode 简介

Unicode 是国际标准字符集,它将世界各种语言的每个字符定义一个唯一的编码,以满足跨语言、跨平台的文本信息转换
Unicode 字符集的编码范围是 0x0000 - 0x10FFFF , 可以容纳一百多万个字符, 每个字符都有一个独一无二的编码,也即每个字符都有一个二进制数值和它对应,这里的二进制数值也叫 码点 , 比如:汉字 “中” 的 码点是 0x4E2D, 大写字母 A 的码点是 0x41, 具体字符对应的 Unicode 编码(码位)可以查询
符号库(https://www.fuhaoku.net/

字节和字符

字节(octet)是一个八位的存储单元,取值范围一定是0~255。而字符(character,或者word)为语言意义上的符号,范围就不一定了。例如在UCS-2中定义的字符范围为0~65535,它的一个字符占用两个字节。

字符集和字符编码

字符集是很多个字符的集合,例如 GB2312 是简体中文的字符集,它收录了六千多个常用的简体汉字及一些符号,数字,拼音等字符
字符编码是 字符集的一种实现方式,把字符集中的字符映射为特定的字节或字节序列,它是一种规则
比如:Unicode 只是字符集,UTF-8、UTF-16、UTF-32 才是真正的字符编码规则

Unicode 字符存储

Unicode 是一个符号集, 它只规定了每个符号的二进制值,但是符号具体如何存储它并没有规定。
多个字节存储有大端和小端两种模式。
小端字节序简写为 LE( Little-Endian ), 表示 低位字节在前,高位字节在后, 高位字节保存在内存的高地址端,而低位字节保存在内存的低地址端
大端字节序简写为 BE( Big-Endian ), 表示 高位字节在前,低位字节在后,高位字节保存在内存的低地址端,低位字节保存在在内存的高地址端
比如字符 0xabcd
大端: ab cd
小端: cd ab

UTF-8 编码

utf-8:是一种变长字符编码,被定义为将码点编码为 1 至 4 个字节,具体取决于码点数值中有效二进制位的数量。

UTF-8 的编码规则:

  1. 对于单字节的符号,字节的第一位设为 0,后面 7 位为这个符号的 Unicode 码。因此对于英语字母,UTF-8 编码和 ASCII 码是相同的, 所以 UTF-8 能兼容 ASCII 编码,这也是互联网普遍采用 UTF-8 的原因之一
  2. 对于 n 字节的符号( n > 1),第一个字节的前 n 位都设为 1,第 n + 1 位设为 0,后面字节的前两位一律设为 10 。剩下的没有提及的二进制位,全部为这个符号的 Unicode 码

UTF-8用1~4个字节来表示代码点。表示方式如下:

码位(点代码)位序列第一字节第二字节第三字节第四字节
U+0000 … U+007F00000000-0xxxxxxx0xxxxxxx
U+0080 … U+07FF00000xxx-xxyyyyyy110xxxxx10yyyyyy
U+0800 … U+FFFFxxxxyyyy-yyzzzzzz1110xxxx10yyyyyy10zzzzzz
U+10000…U+1FFFFF00000000-000wwwxx-
xxxxyyyy-yyzzzzzzz
11110www10xxxxxx10yyyyyy10zzzzzz

Unicode编码转换成 UTF-8

“中”:U+4E2D

  • U+4E2D 在U+0800 ~ u+FFFF 之间,说明可以转换成3个字节的UTF-8
  • U+4E2D 转换成2进制:0100111000101101
  • 根据编码规则得到:11100100 10111000 10101101 ==》》E4 B8 AD
  • U+4E2D的UTF8是:0xE4 0xB8 0xAD

UTF-8 转换成 UTF-16

对于 Unicode 码小于 0x10000 的字符, 使用 2 个字节存储,并且是直接存储 Unicode 码

根据定义,小于 0x10000的字符,只需将UTF-8的值逆推回去,得到的Uncode码就是UTF-16的编码
“中” UTF-8的编码是:0xE4 0xB8 0xAD

  • 将UTF-8 编码转换成2进制,11100100 10111000 10101101
  • 根据UTF-8编码规则,第一个字节取后4位,第二个字节取后6位,第三个字节取6位。
  • 第一个字节取后4位,11100100 & 00001111 = 0000 0100
  • 第二个字节取后6位,10111000 & 00111111 = 0011 1000
  • 第三个字节取后6位,10101101 & 00111111 = 0010 1101
  • 将获取出来的值重新组成2个字节:0100 111000 101101 =01001110 00101101 =4E 2D(UTF-16BE)
*dest++=(*(src)&0x0f<<4) | (*(src + 1)&0x3c>>2)
*dest++=(*(src+1)&0x03<<6) | (*(src + 2)&0x3f)

UTF-16 编码

UTF-16 也是一种变长字符编码, 这种编码方式比较特殊, 它将字符编码成 2 字节 或者 4 字节

UTF-16 具体的编码规则如下:

  • 对于 Unicode 码小于 0x10000 的字符, 使用 2 个字节存储,并且是直接存储 Unicode 码,不用进行编码转换
  • 对于 Unicode 码在 0x10000 和 0x10FFFF 之间的字符,使用 4 个字节存储,这 4 个字节分成前后两部分,每个部分各两个字节,其中,前面两个字节的前 6 位二进制固定为 110110,后面两个字节的前 6 位二进制固定为 110111, 前后部分各剩余 10 位二进制表示符号的 Unicode 码 减去 0x10000 的结果
  • 大于 0x10FFFF 的 Unicode 码无法用 UTF-16 编码

下表是Unicode编码对应UTF-16编码格式

码位(点代码)具体Unicode码(二进制)UTF-16编码方式(二进制)字节
0000 0000 - 0000 FFFFxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxx2
0001 0000 - 0010 FFFFyy yyyyyyyy
xx xxxxxxxx
110110yy yyyyyyyy 110111xx xxxxxxxx4

表格中第一列是Unicode编码的范围,第二列是 具体Unicode码的二进制 ( 第二行的第二列表示的是 Unicode 码 减去 0x10000 后的二进制 ) , 第三列是对应UTF-16编码方式,其中白色的二进制 “1” 和 “0” 是固定的前缀, 字母 x 和 y 表示可用编码的二进制位, 第四列表示 编码占用的字节数

Unicode编码小于0x10000:

“中” 字的 Unicode 码是 4E2D, 它小于 0x10000,根据表格可知,它的 UTF-16 编码占两个字节,并且和 Unicode 码相同,所以 “中” 字的 UTF-16 编码为 4E2D

Unicode编码在0x10000 和 0x10FFFF 之间的字符:

Unicode码是U+11660的,

  1. Unicode码大于0x10000,小于0x10FFFF,按编码规则减去 0x10000,得到值为:0x1660
  2. 0x1660 二进制码位:00000001011001100000,得到一个20位的二进制值。
  3. 1101100000000101 、1101111001100000 转换成16进制 D805 、DE60
  4. UTF-16BE : 0xD8 0x05 0xDE 0x60

UTF-32 编码

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

BOM

BOM 是 byte-order mark 的缩写,是 “字节序标记” 的意思, 它常被用来当做标识文件是以 UTF-8、UTF-16 或 UTF-32 编码的标记
在 Unicode 编码中有一个叫做 “零宽度非换行空格” 的字符 ( ZERO WIDTH NO-BREAK SPACE ), 用字符 FEFF 来表示
对于 UTF-16 ,如果接收到以 FEFF 开头的字节流, 就表明是大端字节序,如果接收到 FFFE, 就表明字节流 是小端字节序
UTF-8 没有字节序问题,上述字符只是用来标识它是 UTF-8 文件,而不是用来说明字节顺序的。“零宽度非换行空格” 字符 的 UTF-8 编码是 EF BB BF, 所以如果接收到以 EF BB BF 开头的字节流,就知道这是UTF-8 文件。
下面的表格列出了不同 UTF 格式的固定文件头

UTF编码固定文件头
UTF-8EF BB BF
UTF-16LEFF FE
UTF-16BEFE FF
UTF-32LEFF FE 00 00
UTF-32BE00 00 FE FF

根据上面的 固定文件头,下面列出了 “中” (U+4E2D)字在文件中的存储 ( 包含文件头 )

编码固定文件头
Unicode 编码0X004E2D
UTF-8EF BB BF 4E 2D
UTF-16BEFE FF 4E 2D
UTF-16LEFF FE 2D 4E
UTF-32BE00 00 FE FF 00 00 4E 2D
UTF-32LEFF FE 00 00 2D 4E 00 00

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值