我正在阅读StringBuffer
的文档,特别是reverse()方法。该文档提到了关于代理对的一些内容。在这种情况下,什么是代理对?什么是低和高代理人?
答案 0 :(得分:114)
术语“代理对”是指在UTF-16编码方案中使用高代码点编码Unicode字符的方法。
在Unicode字符编码中,字符映射到0x0和0x10FFFF之间的值。
在内部,Java使用UTF-16编码方案来存储Unicode文本的字符串。在UTF-16中,使用16位(双字节)代码单元。由于16位只能包含从0x0到0xFFFF的字符范围,因此使用一些额外的复杂度来存储高于此范围(0x10000到0x10FFFF)的值。这是使用称为代理的代码单元对完成的。
代理代码单元分为两个范围,称为“高代理”和“低代理”,具体取决于它们是否允许在双代码单元序列的开头或结尾。
答案 1 :(得分:22)
该文档所说的是,无效的UTF-16字符串在调用reverse
方法后可能会生效,因为它们可能是有效字符串的反转。代理对(讨论here)是UTF-16中的一对16位值,它们编码单个Unicode代码点;低和高代理是编码的两半。
答案 2 :(得分:6)
代理对是指UTF-16对某些字符进行编码的方式,请参阅http://en.wikipedia.org/wiki/UTF-16/UCS-2#Code_points_U.2B10000..U.2B10FFFF
答案 3 :(得分:6)
在this帖子中为上述答案添加更多信息
在java-12中进行了测试,应该可以在5以上的所有Java版本中使用。
如此处所述:https://stackoverflow.com/a/47505451/2987755,
哪个字符(其Unicode高于U + FFFF)表示为代理对,Java将其存储为一对char值,即,单个Unicode字符表示为两个相邻的Java字符。
如以下示例所示。
1.长度:
"".length() //2, Expectations was it should return 1
"".codePointCount(0,"".length()) //1, To get number of Unicode character in Java String
2。平等:
如下使用Unicode \ud83c\udf09
将“”表示为String并检查是否相等。
"".equals("\ud83c\udf09") // true
Java不支持UTF-32
"".equals("\u1F309") // false
3。您可以将Unicode字符转换为Java字符串
"".equals(new String(Character.toChars(0x0001F309))) //true
4。 String.substring()不考虑补充字符
"".substring(0,1) //"?"
"".substring(0,2) //""
"".substring(0,4) //""
要解决此问题,我们可以使用String.offsetByCodePoints(int index, int codePointOffset)
"".substring(0,"".offsetByCodePoints(0,1) // ""
"".substring(2,"".offsetByCodePoints(1,2)) // ""
5。使用BreakIterator迭代Unicode字符串
6.使用Unicode java.text.Collator对字符串进行排序
7.不应使用字符toUppercase,小写字母,而应使用String的大写字母和特定语言环境的小写字母
8. Character.isLetter(char ch)
不支持,最好使用Character.isLetter(int codePoint)
,对于Character类中的每个methodName(char ch)
方法,将有methodName(int codePoint)
类型,可以处理补充字符。
9.在String.getBytes()
中指定字符集,从字节转换为字符串,InputStreamReader
,OutputStreamWriter
参考:
https://coolsymbol.com/emojis/emoji-for-copy-and-paste.html#objects
https://www.online-toolz.com/tools/text-unicode-entities-convertor.php
https://www.ibm.com/developerworks/library/j-unicode/index.html
https://www.oracle.com/technetwork/articles/javaee/supplementary-142654.html
示例image1 image2的更多信息
其他值得探讨的术语:Normalization,BiDi
答案 4 :(得分:3)
代理对是UTF-16中的两个“代码单元”,构成一个“代码点”。 Java文档说明这些“代码点”仍然有效,反向后它们的“代码单元”正确排序。它进一步指出两个不成对的代理代码单元可以被颠倒并形成有效的代理对。这意味着如果有不成对的代码单元,那么反向的反转可能不一样!
请注意,文档中没有提到Graphemes - 这是多个代码点的组合。这意味着e和伴随它的重音仍然可以切换,从而在e之前放置重音。这意味着如果在e之前有另一个元音,它可能会获得e上的重音。
糟糕!
答案 5 :(得分:3)
小序言
在版本3.1之前,使用最多的是8位编码(称为UTF-8)和16位编码(称为UCS-2或“以2个八位位组编码的通用字符集”)。 UTF-8将Unicode点编码为1字节的块序列,而UCS-2始终占用2字节:
A = 41 -带有UTF-8的1个8位块
A = 0041 -具有UCS-2的一个16位块
Ω= CE A9 -两个带UTF-8的8位块
Ω= 03A9 -具有UCS-2的一个16位块
问题
该联合会认为16位就足以覆盖任何人类可读的语言,这给了 2 ^ 16 = 65536 可能的代码值。对于“平面0”(也称为BPM或“基本多语言平面”)而言,这是正确的,它今天包含55,445个65536个代码点。 BPM涵盖了世界上几乎所有人类语言,包括中日韩符号(CJK)。
时间的流逝,并添加了新的亚洲字符集,仅中国符号一项就花费了超过70,000点。现在,甚至还有Emoji points作为标准part的一部分。添加了新的16个“附加” Planes。 UCS-2的房间不足以覆盖比Plane-0大的东西。
Unicode决定
基于UCS-2创建UTF-16。使UTF-16动态,因此每点需要2个字节或4个字节。为UTF-16分配1024点U + D800–U + DBFF,称为“高替代”;将1024个符号U + DC00–U + DFFF(称为低代理)分配给UTF-16。
有了这些更改,BPM在UTF-16中被1个16位的块所覆盖,而所有“补充字符”都被代理对所覆盖,它们分别显示2个块,每个16位,总共1024x1024 = 1 048 576点。
高替代物先于低替代物。与此规则的任何偏差都被认为是错误的编码。例如,没有一对的代理人是不正确的,而高代理人之前的低代理人身份是不正确的。
?,“音乐符号G CLEF”在UTF-16中编码为一对代理0xD834 0xDD1E(2 x 2字节),
在UTF-8中为0xF0 0x9D 0x84 0x9E(4 x 1字节),
在UTF-32中为0x0001D11E(1 x 4字节)。
当前情况
许多历史细节都被禁止遵循主题<。
最新的Unicode标准可在http://www.unicode.org/versions/latest