Unicode 概述
统一码(Unicode)也叫万国码、单一码,由统一码联盟开发,是一种全球通用的字符编码标准,旨在为所有语言、符号和表情符号(Emoji)分配唯一的数字编号(称为 码点,Code Point)。它的核心目标是解决传统字符集(如 ASCII、GB2312、GBK、ISO-8859 等)的兼容性问题,消除乱码,实现跨语言、跨平台的文本一致性。
关键特点:
-
覆盖范围广:支持超过 14 万个字符(截至 Unicode 15.0)。
-
层次化结构:将字符分为平面(Plane),每个平面包含 65,536 个码点。
-
基本多语言平面(BMP, Plane 0):涵盖绝大多数常用字符(U+0000 到 U+FFFF)。
-
辅助平面(Plane 1-16):包含历史文字、表情符号等(如 U+1F600 代表 😀)。
-
-
唯一性:每个字符对应唯一的码点。
-
通用性:覆盖全球所有语言和符号。
-
兼容性:兼容传统编码(如 ASCII)。
-
可扩展性:支持未来新增字符。
Unicode 码点基础
码点结构
- 格式:
U+
+ 4-6位十六进制数(如U+1F600
) - 范围:
- BMP(基本多文种平面):
U+0000
-U+FFFF
- 补充平面:
U+10000
-U+10FFFF
- BMP(基本多文种平面):
编码转换步骤
- 确定码点数值:将
U+XXXX
转换为十进制或十六进制整数 - 按编码规则分段:根据不同编码方式分割为多个代码单元
- 字节序处理:对多字节编码(UTF-16/32)处理字节顺序
- 生成字节序列:将代码单元转换为具体字节值
Unicode 的编码方式
在统一码中,汉字“字”对应的数字是23383。在统一码中,我们有很多方式将数字23383表示成程序中的数据,包括:UTF-8、UTF-16、UTF-32。UTF是“UCS Transformation Format”的缩写,可以翻译成统一码字符集转换格式,即怎样将统一码定义的数字转换成程序数据。
Unicode 码点(如 U+6C49 表示“汉”)需要通过编码方案转换为字节序列。常见的编码方式包括:
1、UTF-8
特点:变长编码(1-4 字节);兼容 ASCII(ASCII 字符占 1 字节);适合网络传输和存储(节省空间)
UTF-8编码规则表
码点范围 | 字节数 | 格式(二进制) |
---|---|---|
U+0000-U+007F | 1 | 0xxxxxxx |
U+0080-U+07FF | 2 | 110xxxxx 10xxxxxx |
U+0800-U+FFFF | 3 | 1110xxxx 10xxxxxx 10xxxxxx |
U+10000-U+10FFFF | 4 | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
注:ASCII 字符(U+0000-U+007F)保持单字节不变!
转换步骤(以 U+6C49
为例)
- 十进制值:
27721
- 二进制:
0110 1100 0100 1001
- 分段填充:
1110xxxx 10xxxxxx 10xxxxxx ↓ 填充 11100110 10110001 10001001
- 十六进制表示:
E6 B1 89
2、UTF-16
特点
变长编码(2 或 4 字节);
基本多语言平面(BMP)字符用 2 字节,辅助平面字符用 4 字节(代理对机制);
广泛用于 Java、Windows 系统。
基本机制
如果码点<0x10000,码点U的UTF-16编码就是U对应的16位无符号整数。
如果码点≥0x10000,我们先计算U'=U-0x10000,然后将U'写成二进制形式:yyyy yyyy yyxx xxxx xxxx,U的UTF-16编码(二进制)就是:110110yyyyyyyyyy 110111xxxxxxxxxx。
- 基本单位:2字节(16位)
- 代理对:当码点 > U+FFFF 时使用两个代理单元
- 高代理(High Surrogate):
U+D800
-U+DBFF
- 低代理(Low Surrogate):
U+DC00
-U+DFFF
- 高代理(High Surrogate):
转换公式(以 U+1F000
为例)
- 计算偏移量:
U+1F600 - U+10000 = 0xF000
- 高代理:
0xD800 + (0xF000 >> 10) = D83C
- 低代理:
0xDC00 + (0xF000 & 0x3FF) = DE00
- 最终表示:
D83C DE00
字节序标记(BOM)
BOM 字节序列 | 含义 |
---|---|
FE FF | UTF-16BE(大端) |
FF FE | UTF-16LE(小端) |
3、UTF-32
特点
定长编码(固定 4 字节);
直接存储码点,处理简单但空间效率低;
适用于需要快速随机访问的场景。
直接映射
- 每个码点直接对应 4 字节(32位)
- 示例:
U+6C49
→0x00006C49
(大端)或496C0000
(小端)
字符:A (U+0041)
内存布局(大端):
00000000 00000041
内存布局(小端):
41000000 00000000
4、BOM(字节顺序标记)
作用:标识文本的字节序(大端序或小端序)和编码类型。
常见 BOM 值:
-
UTF-8:
EF BB BF
-
UTF-16 LE: FF FE
-
UTF-16 BE: FE FF
-
UTF-32 LE : FF FE 00 00
-
UTF-32 BE : 00 00 FE FF
编程实现示例
Python:
# UTF-8 编码
text = "😊"
utf8_bytes = text.encode('utf-8')
print(utf8_bytes.hex()) # f09f988a
# UTF-16 编码
utf16_bytes = text.encode('utf-16-be')
print(utf16_bytes.hex()) # d83dde00
# 码点转换
code_point = ord('😊') # 128522
hex_value = hex(code_point) # '0x1f60a'
Java:
String text = "😊";
// UTF-8 编码
byte[] utf8 = text.getBytes(StandardCharsets.UTF_8);
// UTF-16 编码
byte[] utf16be = text.getBytes("UTF-16BE");
// 码点操作
int codePoint = text.codePointAt(0);
JavaScript:
const text = '😊';
// 获取码点
const codePoint = text.codePointAt(0); // 128522
// 手动转换函数
function codePointToUTF8(cp) {
if (cp < 0x80) return [cp];
// ...
}
PS:unicode里的emoji表情编码可看以下网站
EMOJIALL网站 :Emoji ZWJ 序列