重温UTF-8和UTF-16

一、UTF-8

UTF-8 的全称为: Unicode Transformation Format - 8 - bit

  • Unicode 统一字符集,给世界上所有文字分配唯一编号
  • Transformation Format 转换格式
  • 8-bit 以8位(一个字节) 为基本单位进行编码

UTF-8 是一种把Unicode字符编码成1~4个字节的编码方式

变长编码:

  1. 英文: 1个字节
  2. 拉丁字母: 2个字节 (拉丁字母和希腊字母)
  3. 中文: 3个字节 (大多数常见汉字)
  4. Emoji: 4字节 (包括生僻字符)

编码规则:

  1. 对于长度为1字节的字符,将最高位设置为0.
  2. 对于长度为n字节的字符(n > 1),将首个字节的高n位都设置为1,第n+1位设置为0;从第二个字节开始,将每个字节的高2位都设置为10;

理解: 如果读到一个Byte,那么就取第一位,如果是0,那么就是Ascii码。如果是1,那么继续取值,直到0,有几个1就是几个字符长度。读取后面字符后,组装成一个有效的Unicode码。

举例: "算"字的

Unicode是 U+7B97:

7 B 9 7

0111 1011 1001 0111

UTF-8的编码为 0xE7AE97

E 7 A E 9 7

1110 0111 1010 1110 1001 0111

UTF-16的编码为 0x7B97

7 B 9 7

0111 1011 1001 0111

二、 UTF-16编码: 2或4字节

  1. 2个字节: 当码点在 U+0000 到 U+FFFF,不在代理区 U+D800 到 U+FFFF
  2. 4个字节: 当码点在U+10000 到 U+10FFFF时,使用代理对计算

代理对计算规则:

Unicode有一段特别的区间: U+D800 到 U+DFFFF 不是字符,仅仅是UTF-16的代理对。

当码点 >= 0x10000 时:

  1. 减去0x10000

    1. U = codePoint - 0x10000
  2. 拆成高10位和低10位

    1. high = U >> 10
    2. low = U & 0x3FF
  3. 加上代理基值

    1. 高代理 = 0xD800 + high
    2. 低代理 = 0xDC00 + low
  4. 得到4字节的UTF-16编码

解析UTF-16逻辑:

  1. 先取2个字节;
  2. 如果该值落在0xD800到0xDBFF,说明这是高代理,需要再取2个字节组成4个字节字符。
  3. 再取的2个字节在0xDC00到0xDFFF内。
  4. 否则该字符就是2字节表示。

举例:

  1. 读取到 0xD83D
  2. 因为0xD83D在 0xD800到0xDBFF之间,说明是高代理 0xD83D - 0xD800 = 0x3D
  3. 再获取2字节,读取到0xDE00
  4. 因为0xDE00在0xDC00到0xDFFFF之间,说明是低代理 0xDE00 - 0xDC00 = 0x200
  5. 计算 0x3D << 10 + 0x200 + 0x10000 = 0xF400 + 0x10200 = 0x1F600

结果为 0xD83D的Unicode值为 😀(U+1F600)

知识点:

  1. 使用UTF-16编码的语言有Java、JavaScript、TypeScript和C#。
  2. 网络传输时使用UTF-8格式,以达到最优的兼容性和空间效率。
相关推荐
Puslar2 天前
Agent系列二:项目架构设计
agent·全栈
泥秋哥2 天前
从 0 到上线:NestJS 微服务 + Next.js 管理后台(AI全栈实战)
全栈
腾讯云云开发4 天前
CloudBase把一套完整的 Vibe Coding 平台开源了
后端·全栈·vibecoding
EOPG4 天前
正式入驻爱发电!软硬件全栈开发者的开源创作计划
物联网·开源·全栈·爱发电
Bigger5 天前
🔥 一份 Agent 工程岗 JD,暴露了市场真正想要什么样的人
前端·agent·全栈
bonechips5 天前
从 ”user-chat“ 项目看前后端分离、模块化与 DOM 编程
全栈
星栈5 天前
订单状态机别写散:我在 Rust CRM 里把 6 个状态收进领域模型
后端·rust·全栈
前端双越老师5 天前
普通程序员有没有必要学习 Agent 开发?
前端·agent·全栈
AskHarries5 天前
我如何从1000个产品里筛出方向
人工智能·产品·全栈