在 Java 中:
如果我打印
"123\u202e987\u202c456abc"
那么结果是 123987456abc如果我打印
"123\u202e987\u202cxyzabc"
那么结果是 123987xyzabc
您会看到,当要打印的字符串中的“456”更改为“xyz”时,输出序列不同。
这是如何工作的?
最佳答案
TLDR:出现您所看到的效果是因为 Unicode 算法对数字和字母字符的处理方式不同,该算法确定包含格式控制字符的文本的呈现。
对于您正在显示的文本:
- \u202e 是 RIGHT-TO-LEFT OVERRIDE (RLO) 字符。
- \u202c 是 POP DIRECTIONAL FORMATTING (PDF) 字符。
- 两者都是 Unicode 格式的控制字符,它们的唯一作用是影响输出文本的外观。
- 在您的示例中,RLO 字符指定后面的文本将从右向左显示 (RLO),而 PDF 字符取消(“弹出”)RLO 的效果。
这解释了为什么示例中的文本 123\u202e987\u202cxyzabc 呈现为 123987xyzabc。 RLO (\u202e) 导致后面的文本按从右到左的顺序呈现(因此 987 显示为 789),并且 PDF (\u202c) 终止反转后续文本。
但它并没有解释为什么 123\u202e987\u202c456abc 呈现为 123456789abc。根据这个参数,预期输出应该是 123789456abc。
用于确定此类场景中的输出的算法非常复杂,但其中一个因素是所渲染的字符的方向性。字母字符的方向性较强,而数字(即数字字符)的方向性较弱。有关完整详细信息,请参阅 Unicode 文档 Unicode® Standard Annex #9 UNICODE BIDIRECTIONAL ALGORITHM ,特别是 3.3.4 Resolving Weak Types 部分
该文档 provides an example similar to yours 的文本包含 RIGHT-TO-LEFT EMBEDDING (RLE) 字符(而不是 RLO),后面跟着一个 PDF 和一些包含数字的尾随文本:
Memory: it is called "[RLE]AN INTRODUCTION TO java[PDF]" - $19.95 in hardcover.
Display: it is called "$19.95 - "java OT NOITCUDORTNI NA in hardcover.
请注意,在他们的示例中,移动的不仅仅是数字。美元符号和句点也是如此,因为文本 $19.95 中的所有六个字符都具有弱方向性。
注释:
- 您可以使用 Character.getDirectionality(int codePoint) 获取 Java 中任何 Unicode 字符的方向性类别
- 上面链接的 Unicode 文档需要大量阅读。双向文本的基本介绍包括 W3C 的 Unicode Bidirectional Algorithm basics 和 Unicode 的 Writing Direction and Bidirectional Text FAQ 。
关于java - 为什么 Unicode u+202e 和 u+202c 会导致输出文本有不同的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72051853/