Unicode OverView

Foundation

Unicode:是一种字符编码标准,旨在为全球所有文字和符号提供唯一的编码。

统一编码:不同于其他字符集,Unicode 为每一个字符赋予唯一的码点,避免了字符冲突。

全球化支持:使不同语言和符号能够在计算机系统中一致地表示和处理。

互操作性:解决不同字符集之间的兼容性问题,使得数据交换和文档传输更加顺畅。

起源:Unicode 由国际 Unicode 联盟(Unicode Consortium)于1987年开始开发。

Unicode 字符集

字符

字符是指书写系统中的基本单位,包括字母、数字、符号、标点符号等。

Unicode支持的字符类型包括

  • 基本拉丁字母(Basic Latin):包括英文字母、数字、基本的标点符号等。例如:A, B, C, 1, 2, 3, !, ?, .
  • 拉丁字母扩展(Latin Extended):包括带有变音符号的拉丁字母,如à, é, ñ等。
  • 标点符号和符号(Punctuation and Symbols):各种标点符号、数学符号、货币符号等。例如:$, %, +, =, ©, ™, ♠, ♥
  • 数字(Numbers):阿拉伯数字、罗马数字、上标和下标数字等。例如:123, Ⅳ, ², ₃
  • 表情符号(Emojis):如😀, 😂, ❤️, 🎉等。
  • 特殊字符和符号(Special Characters and Symbols):如•, ‼, ※, †等。
  • 音乐符号(Musical Symbols):如𝄞, 𝄢, 𝄪等。
  • 数学字母数字符号(Mathematical Alphanumeric Symbols):如𝒜, 𝒞, ℬ, ℰ, 𝔄, 𝔊等。
  • 中文汉字(CJK Unified Ideographs):包括中文、日文、韩文的常用汉字。例如:你, 好, 日本, 韓國
  • 其他语自然语言等。。。

码点(Code Point)

编码字符集是一组字符,每个字符都被分配了唯一的数字。编码字符集的单位称为码点。码位值表示字符在编码字符集中的位置。

码点(码位)是 Unicode 字符集中每个字符的唯一标识,通常表示为 U+XXXX 的形式,其中 XXXX十六进制数字。

码点范围从 U+0000 到 U+10FFFF,其中:

  • U+0000 到 U+007F:ASCII 字符集,包含基本的英文字母、数字和控制字符。
  • U+0080 到 U+FFFF:包含各种语言的字符和符号,涵盖拉丁字母扩展、希腊字母、汉字等。
  • U+10000 到 U+10FFFF:称为辅助平面,包含较少使用的字符和符号,如历史文字、表情符号等。

码元(Code Unit)

码元是编码字符数据所用的基本单元。不同的编码方式使用不同大小的码元。例如:

  • UTF-16 使用一个或两个 16 位的码元表示一个字符。
  • UTF-8 使用一个到四个 8 位的码元表示一个字符。
  • UTF-32 使用一个 32 位的码元表示一个字符。

编码范围

基本多文种平面 (BMP) 是从 U+0000 到 U+FFFF,包含大多数常用拉丁字母、希腊字母、汉字、标点符号、控制字符。

辅助平面:分为多个不同的平面,每个平面有特定的用途:

  • 辅助多文种平面 (SMP):从 U+10000 到 U+1FFFF,包含历史文字、音乐符号、数学符号等。
  • 辅助标点平面 (SIP):从 U+20000 到 U+2FFFF,主要用于扩展汉字字符。
  • 辅助专用区平面 (SSP):从 U+E0000 到 U+EFFFF,供私人使用的字符区域。
  • 字符备用区 (PUA):从 U+F0000 到 U+10FFFF,供用户自定义字符。

unicodeplanes

更详细的Unicode字符平面映射

Unicode 编码方式

Unicode 编码方式是指将 Unicode 字符转换为字节序列的方式。

常见的 Unicode 编码形式有 UTF-8UTF-16UTF-32。不同的编码形式在处理效率、存储空间和兼容性方面有所不同。

UTF-8

UTF-8(8-bit Unicode Transformation Format)是一种用于表示 Unicode 字符的可变长度字符编码。 它是一种广泛使用的编码方式,特别适用于互联网和电子邮件,因为它向后兼容 ASCII 并且能够有效地编码所有 Unicode 字符。

编码规则

UTF-8 使用 1 至 4 个字节编码 Unicode 字符,根据字符的不同范围选择不同的字节数:

  1. 1字节:用于 ASCII 码字符(U+0000 至 U+007F)。
  2. 2字节:用于大部分拉丁字母及其他语言的字符(U+0080 至 U+07FF)。
  3. 3字节:用于几乎所有的基本多语言平面字符(U+0800 至 U+FFFF)。
  4. 4字节:用于补充平面字符(U+10000 至 U+10FFFF)。

具体的编码规则如下:

  • 1 字节:0xxxxxxx (7 位)
  • 2 字节:110xxxxx 10xxxxxx (5 + 6 = 11 位)
  • 3 字节:1110xxxx 10xxxxxx 10xxxxxx (4 + 6 + 6 = 16 位)
  • 4 字节:11110xxx 10xxxxxx 10xxxxxx 10xxxxxx (3 + 6 + 6 + 6 = 21 位)

Note

x的补充规则:是将转换后的二进制从高位到低位依次补充。具体看下列例子,

编码示例

示例1: 字符 “A” UTF-8 编码

  1. 获取其Unicode码点:U+004116U+0041_{16}
  2. 转换为二进制:0100 0001
  3. 获取所需要的字节数:U+0041在 U+0000 到 U+007F范围内,因此需要一个字节
  4. 得到对应字节的编码规则以及按高位到低位补码:0xxxxxxx \to 0100 0001
  5. UTF-8表示:411641_{16}

示例1: 字符 “你” UTF-8 编码

  1. 获取其Unicode码点:U+4F6016U+4F60_{16}
  2. 转换为二进制:0100 1111 0110 0000
  3. 获取所需要的字节数:U+4F60U+4F60在 U+0800 至 U+FFFF范围内,因此需要三个字节
  4. 得到对应字节的编码规则以及按高位到低位补码:1110xxxx 10xxxxxx 10xxxxxx \to 11100100 10111101 10100000
  5. UTF-8表示:E4BDA016E4BDA0_{16}

UTF-16

UTF-16(16-bit Unicode Transformation Format)是一种将 Unicode 字符编码为16位宽字符的编码方式。 它可以编码整个 Unicode 字符集(U+0000U+0000U+10FFFFU+10FFFF),并且使用一种可变长度的编码格式来处理不同的字符范围。

Note

16位宽字符

在早期的计算机系统中,字符通常使用 8 位(一个字节)表示,最多可以表示 256 个字符(如 ASCII 编码)。 但是,随着计算机的普及,特别是在需要处理多种语言的国际环境中,256 个字符远远不够。因此,Unicode 标准被引入, 试图为每种语言的所有字符分配一个唯一的代码点。

为了处理 Unicode 字符集中的大量字符,尤其是那些超出 8 位表示范围的字符,16 位宽字符被引入。 这种表示方式使用 16 位(2 字节)来表示一个字符,可以表示最多 65536(216)个不同的字符。

基本原理

  1. 基本多文种平面 (BMP)
  • 范围: U+0000 到 U+FFFF
  • BMP内的字符用一个16位单元表示
  1. 补充平面
  • 范围:U+10000 到 U+10FFFF
  • 超出BMP的字符使用一对16位单元表示,称之为代理对

编码规则

  1. BMP内的字符 BMP 内的字符直接用一个 16 位单元表示,其值与 Unicode 码点相同。

  2. 代理对 对于补充平面字符(码点大于 U+FFFF),UTF-16 使用两个 16 位单元:

  • 高代理项(High Surrogate):从 U+D800 到 U+DBFF。
  • 低代理项(Low Surrogate):从 U+DC00 到 U+DFFF。

代理对的计算

对于一个 Unicode 码点 U(大于 U+FFFF),其代理对的计算步骤如下:

  1. 减去 U+10000,得到一个 20 位的数。
  2. 将这个 20 位的数分成高 10 位和低 10 位。
  3. 高 10 位加上 U+D800,得到高代理项。
  4. 低 10 位加上 U+DC00,得到低代理项。

编码示例

示例1: 字符 ”😊“(U+1F60A) UTF-16 编码过程

  1. 确定字符Unicode码点
  • 码点为U+1F60A
  • 减去 0x10000: 0x1F60A - 0x10000 = 0xF60A
  1. 分解为高10位和低10位
  • 高10位:(0x0F60A >> 10) & 0x3FF = 0x03C
  • 低10位:0x0F60A & 0x3FF = 0x0AA
  1. 计算高代理项和低代理项:
  • 高代理项:0xD800 + 0x03C = 0xD83D
  • 低代理项:0xDC00 + 0x0AA = 0xDE0A
  1. UTF-16编码结果
  • 代理对: 0xD83D 0xDE0A

Pitfall

  1. 0xF60A >> 10 意味着将码点 0xF60A 向右移动 10 位。在二进制操作中,右移 10 位相当于将最高的 10 位移除,剩下的低位。 对于码点 0xF60A,移位后得到的结果是 0x3D。
  2. & 0x3FF 是为了确保结果不超过 10 位二进制数的范围, 在二进制操作中,& 0x3FF 是为了保留最低的 10 位。

使用JavaScript进行UTF-16编码

function utf16Encode(codePoint) {
if (codePoint <= 0xFFFF) {
// Basic Multilingual Plane (BMP) character
return String.fromCharCode(codePoint);
} else {
// Supplementary Plane character (U+10000 - U+10FFFF)
codePoint -= 0x10000;
let highSurrogate = 0xD800 + (codePoint >> 10);
let lowSurrogate = 0xDC00 + (codePoint & 0x3FF);
return String.fromCharCode(highSurrogate, lowSurrogate);
}
}

UTF-32

UTF-32 是一种将 Unicode 字符编码为固定长度的 32 位整数(4 字节)的编码形式。 每个 Unicode 码点直接映射到一个 32 位整数,因此所有字符的编码长度是固定的 4 字节。 这使得 UTF-32 的计算和处理非常简单,因为你可以直接按 4 字节来读写和索引字符。

主要特点:

  1. 固定长度:每个字符始终占用 4 个字节,不像 UTF-8 或 UTF-16 那样使用可变长度的编码。这个特性使得字符的索引和处理非常简单。
  2. 直接映射:每个 Unicode 码点直接映射到一个 32 位整数,编码和解码过程不需要复杂的算法。
  3. 空间效率低:因为每个字符都占用 4 个字节,所以 UTF-32 在空间利用率上较低,特别是对于主要使用基本多文种平面(BMP,码点范围为 U+0000 到 U+FFFF)的文本来说,UTF-32 比 UTF-8 或 UTF-16 要浪费更多的存储空间。

编码示例

示例1: 字符 ”A“(U+1F60A) UTF-32 编码过程

  1. Unicode码点是U+0041
  2. UTF-32编码为:U+00000041

使用场景

UTF-32 通常用于内存空间不是问题且需要高效随机访问字符的应用场景。例如:

  • 某些特定的系统和工具可能内部使用 UTF-32 进行字符串处理,以便简化代码和提高处理速度。
  • 某些高性能计算环境中,UTF-32 的固定长度特性可能有助于简化并加速文本处理算法。

差异以及对比

特性UTF-8UTF-16UTF-32
编码长度可变长度(1-4 字节)可变长度(2 或 4 字节)固定长度(4 字节)
编码范围U+0000 到 U+10FFFFU+0000 到 U+10FFFFU+0000 到 U+10FFFF
字符表示ASCII 字符占 1 字节,多字节表示非 ASCII 字符BMP 字符占 2 字节,辅助平面字符占 4 字节所有字符占 4 字节
空间效率高效,特别是对 ASCII 字符中等,对于 BMP 字符较高效低,所有字符均占 4 字节
处理复杂度较高,需要处理可变长度编码较高,需要处理代理对简单,固定长度
字符索引较复杂,需要遍历字符较复杂,需要处理代理对简单,直接按 4 字节索引
应用场景网络传输、文件存储、系统接口内存表示、文件存储、某些网络协议内存表示、某些高性能计算
优点高效的空间利用率,特别适合 ASCII 文本对 BMP 字符高效,广泛支持编码和解码简单,固定长度便于处理
缺点处理复杂,字符索引困难处理代理对复杂,空间利用率较低空间利用率低,浪费内存

Unicode 常用工具

字符映射表

字符映射表工具用于查看和搜索 Unicode 字符及其属性。常见的字符映射表工具包括:

  1. Unicode Character Table: 提供完整的 Unicode 字符列表,支持按字符名称、码点、块进行搜索。
  2. Unicode.org Code Charts: 提供官方的 Unicode 代码图,按块和范围显示字符,包含详细的字符信息。

字符转换工具

字符转换工具用于在不同编码之间转换字符。常见的字符转换工具包括:

  1. Online Unicode Converter: 支持将文本在 UTF-8、UTF-16、UTF-32 和其他编码之间相互转换。
  2. JavaScript Unicode Converter: 使用 JavaScript 库将字符在不同编码之间转换。

字符检查工具

字符检查工具用于验证字符的有效性,检查字符属性和编码问题。常见的字符检查工具包括:

  1. Unicode Character Inspector: 检查 Unicode 字符的详细信息,包括码点、名称、类别、脚本等。
  2. Unicode Character Properties: 提供 Unicode 字符的属性信息,支持按字符搜索。

编码检测工具

编码检测工具用于检测文本的编码方式,以便正确解码。常见的编码检测工具包括:

  1. dencode: 检测文本的编码方式等信息

除此之外,onlinetools 包含了多种的关于Unicode的工具。

Reference