UTF-16编码原理讲解

文章目录

  • 一、unicode
  • 二、什么是UTF-16
  • 三、编码规则
    • 一个码元
    • 两个码元
  • 四、问题
    • 大端序小端序?
  • 参考


一、unicode

unicode是一个字符集,也称为unicode编码,为每一个字符分配了一个ID,这个ID称为码点

Unicode的编码空间从U+0000到U+10FFFF,共有1,112,064个码位(code point)可用来映射字符。Unicode的编码空间可以划分为17个平面(plane),每个平面包含216(65,536)个码位。17个平面的码位可表示为从U+xx0000到U+xxFFFF,共计17个平面。第一个平面称为基本多语言平面(Basic Multilingual Plane, BMP),或称第零平面(Plane 0),其他平面称为辅助平面(Supplementary Planes)。基本多语言平面内,从U+D800到U+DFFF之间的码位区段是永久保留不映射到Unicode字符。UTF-16就利用保留下来的0xD800-0xDFFF区段的码位来对辅助平面的字符的码位进行编码
UTF-16编码原理讲解_第1张图片


二、什么是UTF-16

UTF-16(16 bit Unicode Transformation Format)即16位的Unicode转换格式,以16位即双字节为编码单元
UTF-16的编码对象就是unicode


三、编码规则

一个码元

我们常用到的字符都在unicode的第一个平面,也就是基本多语言平面(Basic Multilingual Plane, BMP),范围是0x0000-0xFFFF

UTF-16以两个字节为一个编码单位,范围是 0x0000 - 0xFFFF。我们称为码元
当我们使用的字符unicode码点在 0x0000 - 0xFFFF的时候
utf-16的编码和unicode的编码是一一对应的
比如 “”的码点是 6211, 在多语言平面内,所以UTF-16编码也是 6211

两个码元

码点范围 0x10000 - 0x10FFFF的字符已经无法使用1个编码单位来标识,所以此时需要两个码元
比如这个字符的码点为 U+1F602

将码点范围左移 0x10000,此时码点范围是 0x0 - 0xFFFFF, 为什么要移这一下子呢,因为0x10FFFF有21位,左移完只有20位,更好做拆分
将的码点同样进行左移

0x1F602 - 0x10000 = 0xf602

展开为20位,并分为两组,10位一组

0000111101 1000000010

将这组数据放入两个码元中(一个编码单位为两字节(16位)),其余补0

xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx	# 两个码元
xxxxxx0000111101 xxxxxx1000000010		# 填充
0000000000111101 0000001000000010		# 补0
0x3D 0x202

得到第一个码元或称作高位代理(high surrogate)
得到第二个码元或称作低位代理(low surrogate)
现在一个码元的范围是 0 - 0x3FF(10位bit最高可表示0x3FF)

在多语言平面中,从U+D800到U+DFFF之间的码位区段是永久保留不映射到Unicode字符,其大小为

0xDFFF - 0xD800 = 0x7FF

而一个码元的范围在 0x3FF, 所以将该码元移动到该区域

高位代理移动

0x3D + 0xD800 = 0xD83D

地位代理移动
高位代理占用了0x3FF的空间,所以地位代理要从 0xD800 + 0x3FF + 1 的地方开始移动

0xDC00 + 0x202 = 0xDE02

所以的最终编码就是 0xD8 0x3D 0xDE 0x02


四、问题

大端序小端序?

这里以notepad++编辑器举例(其他编辑器也有可能有这个问题)
UTF-16编码原理讲解_第2张图片
这里的Big Endian为大端序,另一个就是小端序了,如果你想看到正确的显示效果那么就选择大端序
,使用二进制编辑器打开时会发现文件开头有 FE FF,这是BOM,忽略即可,从后面开始看
详细可以参考: https://blog.csdn.net/qq_56313338/article/details/133788268

参考

  • bilibili

你可能感兴趣的:(UTF-16,编码)