什么是 UTF-8 中的代理字符?

Ghe*_*man 6 utf-8 utf surrogate-pairs

我有一个奇怪的验证程序,它验证 utf-8 字符串是否是有效的主机名(PHP 中的 Zend Framework 主机名验证器)。它允许 IDN(国际化域名)。它将每个子域与其十六进制字节表示定义的字符集进行比较。两个这样的集合是D800-DB7FDC00-DFFFpreg_match在这些比较过程中调用的 PHP 正则表达式比较函数失败,它表示DC00-DFFF该函数中不允许使用字符。从维基百科我了解到这些字节在 UTF-8 中被称为代理字符。什么是它们,它们实际上对应哪些字符?我在几个地方读过我仍然不明白它们是什么。

Tom*_*get 13

什么是 UTF-8 中的代理字符?

这几乎就像一个技巧问题。

近似答案 #1:4 个字节(如果以 UTF-8 配对和编码)。

近似答案 #2:无效(如果未配对)。

近似答案 #3:它不是 UTF-8;它是经过修改的 UTF-8

概要:该术语不适用于 UTF-8。

Unicode 代码点的范围需要 21 位数据。

UTF-16 代码单元是 16 位。UTF-16 将一些 Unicode 代码点范围编码为一个代码单元,将其他代码点编码为两个代码单元对,第一个来自“高”范围,第二个来自“低”范围。Unicode 将与高低对范围匹配的代码点保留为无效。他们有时被称为代理人,但他们不是角色。它们本身没有任何意义。

UTF-8 编码单元为 8 位。UTF-8 分别以一到四个代码单元对几个不同的代码点范围进行编码。

#1 碰巧 UTF-16 用两个 16 位代码单元编码的代码点,UTF-8 用 4 个 8 位代码单元编码,反之亦然。

#2 您可以将 UTF-8 编码算法应用于无效的代码点,这是无效的。它们无法解码为有效的代码点。兼容的读取器会抛出异常或抛出字节并插入替换字符 (?)。

#3 Java 提供了一种使用名为 JNI 的系统在外部代码中实现功能的方法。Java String API 提供对作为 UTF-16 代码单元的 String 和 char 的访问。在 JNI 的某些地方,大概是为了方便,字符串值被修改为 UTF-8。Modified UTF-8 是应用于 UTF-16 代码单元而不是 Unicode 代码点的 UTF-8 编码算法。

无论如何,字符编码的基本规则是使用用于写入的编码进行读取。如果要将任何字节序列视为文本,则必须知道编码;否则,您会丢失数据。