Ray*_*ond 139 java unicode utf-16 surrogate-pairs
我正在阅读文档StringBuffer,特别是reverse()方法.该文件提到了代理人对的一些内容.在这种情况下,什么是代理对?什么是低和高代理人?
Jef*_*dge 119
术语"代理对"是指在UTF-16编码方案中用高代码点编码Unicode字符的方法.
在Unicode字符编码中,字符映射到0x0和0x10FFFF之间的值.
在内部,Java使用UTF-16编码方案来存储Unicode文本的字符串.在UTF-16中,使用16位(双字节)代码单元.由于16位只能包含从0x0到0xFFFF的字符范围,因此使用一些额外的复杂度来存储高于此范围(0x10000到0x10FFFF)的值.这是使用称为代理的代码单元对完成的.
代理代码单元在两个范围内称为"高代理"和"低代理",这取决于它们是否允许在双代码单元序列的开头或结尾.
ibr*_*ban 49
早期Java版本使用16位char数据类型表示Unicode字符.这种设计在当时是有意义的,因为所有Unicode字符的值都小于65,535(0xFFFF),并且可以用16位表示.但是,稍后,Unicode将最大值增加到1,114,111(0x10FFFF).由于16位值太小而无法表示Unicode版本3.1中的所有Unicode字符,因此UTF-32编码方案采用32位值(称为代码点).但是为了有效使用内存,16位值优于32位值,因此Unicode引入了一种新设计,允许继续使用16位值.采用UTF-16编码方案的这种设计将1624个值分配给16位高代理(在U + D800到U + DBFF范围内),另外1,024个值分配给16位低代理(在U + DC00范围内)到U + DFFF).它使用高代理,后跟低代理 - 代理对 - 代表(1,024和1,024的乘积)1,048,576(0x100000)值介于65,536(0x10000)和1,114,111(0x10FFFF)之间.
Jer*_*ock 22
该文档所说的是,无效的UTF-16字符串在调用reverse方法后可能变为有效,因为它们可能是有效字符串的反转.代理对(此处讨论)是UTF-16中的一对16位值,它们编码单个Unicode代码点; 低和高代理是该编码的两半.
dkb*_*dkb 11
向此帖子的以上答案中添加更多信息
在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
Run Code Online (Sandbox Code Playgroud)
2.相等性:如下
使用Unicode表示“”为String \ud83c\udf09并检查相等性。
"".equals("\ud83c\udf09") // true
Run Code Online (Sandbox Code Playgroud)
Java不支持UTF-32
"".equals("\u1F309") // false
Run Code Online (Sandbox Code Playgroud)
3.您可以将Unicode字符转换为Java字符串
"".equals(new String(Character.toChars(0x0001F309))) //true
Run Code Online (Sandbox Code Playgroud)
4. String.substring()不考虑补充字符
"".substring(0,1) //"?"
"".substring(0,2) //""
"".substring(0,4) //""
Run Code Online (Sandbox Code Playgroud)
为了解决这个问题,我们可以使用 String.offsetByCodePoints(int index, int codePointOffset)
"".substring(0,"".offsetByCodePoints(0,1) // ""
"".substring(2,"".offsetByCodePoints(1,2)) // ""
Run Code Online (Sandbox Code Playgroud)
5.迭代Unicode字符串与的BreakIterator
6.排序字符串使用Unicode java.text.Collator中
7.字符toUppercase,小写不应使用,相反,使用字符串大写和特定地点的小写
8. Character.isLetter(char ch)不支持,更好使用Character.isLetter(int codePoint),对于每个methodName(char ch)在Character类中的方法将存在methodName(int codePoint)可以处理补充字符的类型。
9.在中指定字符集String.getBytes(),将Bytes转换为String 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
小序
Unicode 表示代码点。每个代码点都可以根据 Unicode 标准以 8 位、16 位或 32 位块进行编码。
在 3.1 版之前,主要使用的是 8 位编码,称为 UTF-8,和 16 位编码,称为 UCS-2 或“以 2 个八位字节编码的通用字符集”。UTF-8 将 Unicode 点编码为 1 个字节的块序列,而 UCS-2 总是占用 2 个字节:
A = 41 - 一个带有 UTF-8 的 8 位块
A = 0041 - 一个带有 UCS-2 的 16 位块
?= CE A9 - 两块 8 位的 UTF-8
?= 03A9 - 一块 16 位的 UCS-2
问题
该联盟认为 16 位足以涵盖任何人类可读的语言,这给出了2^16 = 65536 个可能的代码值。对于平面 0(也称为 BPM 或基本多语言平面)而言,情况确实如此,它包括今天的 65536 个代码点中的 55,445 个。BPM 涵盖了世界上几乎所有人类语言,包括中日韩符号 (CJK)。
随着时间的流逝和新的亚洲字符集的添加,仅中文符号就花费了 70,000 多个点。现在,甚至有表情符号点作为标准的一部分。添加了新的 16 个“附加”平面。UCS-2 房间不足以覆盖比 Plane-0 更大的任何东西。
统一码决定
通过这些更改,BPM 被 UTF-16 中的 16 位块覆盖,而所有“补充字符”都被代理对覆盖,每个块显示 2 个块 x 16 位,总共 1024x1024 = 1 048 576 个点。
高代理先于低代理。任何与此规则的偏差都被视为错误编码。例如,没有一对的代理是不正确的,站在高代理之前的低代理是不正确的。
, 'MUSICAL SYMBOL G CLEF', 在 UTF-16 中编码为一对代理 0xD834 0xDD1E(2 x 2 个字节),
在 UTF-8 中编码为 0xF0 0x9D 0x84 0x9E(4 x 1 个字节),
在 UTF-30010x1E 中编码为 0xD834 0xDD1E (1 x 4 字节)。
现在的情况
许多历史细节被压制以跟随话题?。
最新的 Unicode 标准可以在http://www.unicode.org/versions/latest找到
代理对是指UTF-16对某些字符进行编码的方式,请参阅http://en.wikipedia.org/wiki/UTF-16/UCS-2#Code_points_U.2B10000..U.2B10FFFF
代理对是 UTF-16 中组成一个“代码点”的两个“代码单元”。Java 文档指出,在相反之后,这些“代码点”仍然有效,其“代码单元”顺序正确。它还指出两个不成对的代理代码单元可以颠倒并形成有效的代理对。这意味着如果存在未配对的代码单元,那么逆向的逆向可能会不一样!
但请注意,文档中没有提及任何有关字形的内容——字形是多个代码点的组合。这意味着 e 和随之而来的重音仍然可以交换,从而将重音放在 e 之前。这意味着如果 e 之前有另一个元音,它可能会得到 e 上的重音。
哎呀!