码点是什么
Unicode 为字符集中的每个抽象字符分配一个整数编号,称为码点,记作 U+ 加十六进制(如 U+4E2D 表示「中」)。码点只是编号,编码形式(UTF-8/UTF-16 等)才决定它在存储中的字节。层次要分清:码点(编号)→ 编码单元(UTF-8 是字节,UTF-16 是 16 位单位)→ 字形(字体里画出来的形状)。另外,用户感知的一个字符可能由多个码点组成,例如重音字母的基字母加组合符号,所以码点数与可见字符数并不总是一一对应。
基本信息
| 码点范围 | U+0000 至 U+10FFFF |
|---|---|
| 书写形式 | U+ 加 4 至 6 位十六进制,如 U+4E2D、U+1F600 |
| 保留区间 | U+D800-U+DFFF 为代理区,不分配给任何字符 |
| 与编码的关系 | 码点是编号,编码形式决定字节表示 |
| 与字形的区别 | 字形是字体中的画法,多个码点可能共用或复用字形 |
| 与字符数的区别 | 组合序列使多个码点对应一个可见字符 |
典型使用场景
- 转义写法互转:\u4e2d、中、U+4E2D 表示同一个字符
- 乱码定位:把可疑内容按码点列出,识别出不可见字符与错位组合
- 字符分类校验:判断输入是否落在特定码点区间(如是否含汉字、是否含 emoji)
- 长度口径确认:明确业务要求的是码点数、编码单元数还是字形簇数
- 字体与显示排查:码点正确但显示为方块时,问题在字体而非编码
码点查看示例
码点查看示例
python -c "print(ord('中'), hex(ord('中')))" # 20013 0x4e2d
python -c "print(chr(0x4E2D))" # 由码点还原字符
python -c "print([hex(ord(c)) for c in 'a中'])" # 逐字符列出码点,便于定位
python -c "print('\u4e2d')" # \u 转义(仅覆盖基本平面)
python -c "print('\U0001F600')" # \U 八位转义用于增补平面
python -c "print(len('中'), len('中'.encode('utf-8')))" # 码点数 1,字节数 3概念层次对照
| 概念 | 含义 | 例子 |
|---|---|---|
| 码点 | Unicode 分配的抽象编号 | U+4E2D |
| 编码单元 | 某种编码的最小单位 | UTF-8 的字节、UTF-16 的 16 位单位 |
| 字节 | 存储与传输的实际内容 | 中 在 UTF-8 下是 3 字节 |
| 字形 | 字体中绘制的图形 | 同一码点在不同字体中形状不同 |
| 字形簇 | 用户感知的一个字符单位 | 带组合符号的字母、组合 emoji |
\uXXXX 与 U+XXXX 不是一回事:前者是编程语言与协议里的转义写法,按 UTF-16 语义只覆盖 4 位十六进制,表示增补平面字符要写成代理对;后者是 Unicode 的书写惯例,可以直接写 5 位或 6 位十六进制。
码点正确但显示异常通常不是编码问题:显示为空心方块说明字体缺少对应字形,显示为一串符号可能是渲染器不支持组合序列。排查时先确认码点,再换环境验证。
长度校验要明确口径:按码点、按编码单元还是按字形簇计数,三种结果可能相差一倍以上。接口文档应写明使用哪一种,前后端与数据库长度限制也应按同一口径设计。