我有一个奇怪的验证程序来验证 utf-8 字符串是否是有效的主机名(PHP 中的 Zend Framework Hostname valdiator)。它允许 IDN(国际化域名)。它将每个子域与由其 HEX 字节表示定义的字符集进行比较。两个这样的集合是D800-DB7F
和DC00-DFFF
。在这些比较过程中调用的 PHP 正则表达式比较函数preg_match
失败,它表示DC00-DFFF
此函数中不允许使用字符。从维基百科我了解到这些字节在 UTF-8 中被称为代理字符。什么是 thay 以及它们实际对应的字符是什么?我读了几个地方我仍然不明白它们是什么。
1 回答
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 提供对 String 和 char 作为 UTF-16 代码单元的访问。在 JNI 的某些地方,大概是为了方便,字符串值被修改为 UTF-8。修改后的 UTF-8 是应用于 UTF-16 代码单元而不是 Unicode 代码点的 UTF-8 编码算法。
无论如何,字符编码的基本规则是使用用于写入的编码进行读取。如果要将任何字节序列视为文本,则必须知道编码;否则,您将丢失数据。