我在阅读StringBuffer的文档,特别是reverse()方法。文档中提到了关于 surrogate pairs 的内容。在这种情况下,什么是surrogate pair?什么是 low 和 high surrogate?
StringBuffer
jum4pzuy1#
术语“代理项对”是指在UTF-16编码方案中使用高码位编码Unicode字符的方法。在Unicode字符编码中,字符Map到0x 0和0x 10 FFFF之间的值。在内部,Java使用UTF-16编码方案来存储Unicode文本的字符串。在UTF-16中,使用16位(两字节)代码单元。由于16位只能包含从0x 0到0xFFFF的字符范围,因此使用一些额外的复杂性来存储此范围(0x 10000到0x 10 FFFF)以上的值。这使用称为代理的代码单元对来完成。代理代码单元在称为“高代理”和“低代理”的两个范围内,这取决于它们是否被允许在双代码单元序列的开始或结束处。
tnkciper2#
早期的Java版本使用16位的char数据类型表示Unicode字符。这种设计在当时是有意义的,因为所有Unicode字符的值都小于65,535(0xFFFF),可以用16位表示。然而,后来Unicode将最大值增加到1,114,111(0x 10 FFFF)。由于16位值太小,无法表示Unicode 3.1版中的所有Unicode字符,UTF-32编码方案采用了32位值(称为代码点)。但为了有效使用内存,16位值优于32位值,因此Unicode引入了一种新的设计,允许继续使用16位值。这种设计在UTF-16编码方案中采用,将1,024个值分配给16位高的代理(在U+D800到U+DBFF范围内)和另外1,024个值到16位低位替代值(在U+ DC 00到U+DFFF的范围内)。它使用一个高代理项,后面跟着一个低代理项(一个代理项对)来表示(1,024和1,024的乘积)1,048,576(0x 100000)个介于65,536(0x 10000)和1,114,111(0x 10 FFFF)之间的值。
qfe3c7zg3#
添加一些更多的信息,以上述答案从this后。在Java-12中测试,应该可以在所有Java版本5以上工作。如前所述: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 the number of Unicode characters in a Java String
字符串1.平等:使用Unicode \ud83c\udf09将“”表示为String,如下所示,并检查相等性。
\ud83c\udf09
"🌉".equals("\ud83c\udf09") // true
型Java不支持UTF-32
"🌉".equals("\u1F309") // false
型1.您可以将Unicode字符转换为Java字符串
"🌉".equals(new String(Character.toChars(0x0001F309))) //true
型
"🌉🌐".substring(0,1) //"?" "🌉🌐".substring(0,2) //"🌉" "🌉🌐".substring(0,4) //"🌉🌐"
型为了解决这个问题,我们可以使用String.offsetByCodePoints(int index, int codePointOffset)
String.offsetByCodePoints(int index, int codePointOffset)
"🌉🌐".substring(0,"🌉🌐".offsetByCodePoints(0,1) // "🌉" "🌉🌐".substring(2,"🌉🌐".offsetByCodePoints(1,2)) // "🌐"
型1.使用BreakIterator迭代Unicode字符串1.使用Unicode java.text.Collator排序字符串1.不应使用Character的toUpperCase()、toLowerCase()方法,而应使用特定区域设置的String String和String。
toUpperCase()
toLowerCase()
Character.isLetter(char ch)
Character.isLetter(int codePoint)
methodName(char ch)
methodName(int codePoint)
String.getBytes()
InputStreamReader
OutputStreamWriter
java.lang.Character.isEmoji
public static void main(String[] args) { System.out.println('☺' + " isEmoji : " + isEmoji('☺')); // true System.out.println('❌' + " isEmoji : " + isEmoji('❌')); // true System.out.println('ž' + " isEmoji : " + isEmoji('ž')); // false emojiChecks("A"); emojiChecks("©"); emojiChecks("☺"); emojiChecks("\uD83D\uDE0A"); } private static void emojiChecks(String emoji) { // If any string is not emoji then it can not be moji_Component, Emoji_Presentation, Emoji_Modifier, and Emoji_Modifier_Base. // Ref: https://unicode.org/reports/tr51/#Emoji_Properties_and_Data_Files final Pattern emojiPattern = Pattern.compile("\\p{IsEmoji}"); final Pattern emojiModifierBasePattern = Pattern.compile("\\p{IsEmoji_Modifier_Base}"); final Pattern emojiComponentPattern = Pattern.compile("\\p{IsEmoji_Component}"); final Pattern emojiPresentationPattern = Pattern.compile("\\p{IsEmoji_Presentation}"); final Pattern isExtendedPictographicPattern = Pattern.compile("\\p{IsExtended_Pictographic}"); System.out.println(emoji + " IsEmoji: " + emojiPattern.matcher(emoji).matches()); System.out.println(emoji + " IsEmojiModifierBase: " + emojiModifierBasePattern.matcher(emoji).matches()); System.out.println(emoji + " IsEmojiComponent: " + emojiComponentPattern.matcher(emoji).matches()); System.out.println(emoji + " IsEmojiPresentation: " + emojiPresentationPattern.matcher(emoji).matches()); System.out.println(emoji + " IsExtended_Pictographic: " + isExtendedPictographicPattern.matcher(emoji).matches()); System.out.println("----------------------------------------"); } // output ☺ isEmoji : true ❌ isEmoji : true ž isEmoji : false A IsEmoji: false A IsEmojiModifierBase: false A IsEmojiComponent: false A IsEmojiPresentation: false A IsExtended_Pictographic: false ---------------------------------------- © IsEmoji: true © IsEmojiModifierBase: false © IsEmojiComponent: false © IsEmojiPresentation: false © IsExtended_Pictographic: true ---------------------------------------- ☺ IsEmoji: true ☺ IsEmojiModifierBase: false ☺ IsEmojiComponent: false ☺ IsEmojiPresentation: false ☺ IsExtended_Pictographic: true ---------------------------------------- 😊 IsEmoji: true 😊 IsEmojiModifierBase: false 😊 IsEmojiComponent: false 😊 IsEmojiPresentation: true 😊 IsExtended_Pictographic: true ----------------------------------------
型参考号:https://coolsymbol.com/emojis/emoji-for-copy-and-paste.html#objectshttps://www.online-toolz.com/tools/text-unicode-entities-convertor.phphttps://www.ibm.com/developerworks/library/j-unicode/index.htmlhttps://www.oracle.com/technetwork/articles/javaee/supplementary-142654.html更多关于image1image2的信息其他值得探讨的术语:标准化,BiDi
ioekq8ef4#
该文档的意思是,无效的UTF-16字符串在调用reverse方法后可能会变为有效,因为它们可能是有效字符串的反转。代理项对(这里讨论)是一对UTF-16中的16位值,它们编码单个Unicode代码点;低代理项和高代理项是该编码的两部分。
reverse
kkbh8khc5#
小序
该联盟认为16位将足以覆盖任何人类可读的语言,它给出了 2^16 = 65536 可能的代码值。这对于平面0来说是正确的,也被称为BMP或基本多语言平面,它包括今天65536个代码点中的55,445个。BMP几乎覆盖了世界上所有的人类语言,包括中国-日本-韩国符号(CJK)。随着时间的推移,新的亚洲字符集被添加进来,仅中文符号就占据了70,000多个点。现在,甚至有Emoji points作为标准的Emoji points的一部分。新的16个“额外”Planes被添加进来。UCS-2房间不足以覆盖比Plane-0更大的东西。
Unicode决定
1.将Unicode限制为17个平面×每个平面65 536个字符= 1 114 112个最大点。1.目前的UTF-32,以前称为UCS-4,为每个代码点保存32位,并覆盖所有平面。1.继续使用UTF-8作为动态编码,将每个码点的UTF-8限制为最大4字节,即每个码点从1字节到4字节。1.弃用UCS-21.基于UCS-2创建UTF-16。将UTF-16设置为动态的,因此每个点占用2个字节或4个字节。将1024个点U+D800-U+DBFF(称为高位替代)分配给UTF-16;将1024个符号U+ DC 00-U+DFFF(称为低位替代)分配给UTF-16。通过这些变化,BMP被UTF-16中的1个16位块覆盖,而所有“补充字符”被代理对覆盖,每个代理对呈现2个16位块,总共1024 x1024 = 1 048 576点。
𝄞“MUSICAL SYMBOL G CLEF”,以UTF-16编码为一对代理0xD 834 0xDD 1 E(2 × 2字节),在UTF-8中为0xF 0 0x 9D 0x 84 0x 9 E(4 × 1字节),在UTF-32中为0x 0001 D11 E(1 × 4字节)。
目前情况
为了支持具有不正确的UTF-8/UTF-16编码的遗留应用程序,创建了一个新的标准WTF-8,即Wobbly Transformation Format。它支持任意代理点,例如非配对的代理或不正确的序列。今天,一些产品不符合该标准,并将UTF-8视为WTF-8。
许多历史细节被压制,以遵循主题。最新的Unicode标准可以在http://www.unicode.org/versions/latest上找到
7gcisfzg6#
替代对指的是UTF-16编码某些字符的方式,请参阅http://en.wikipedia.org/wiki/UTF-16/UCS-2#Code_points_U.2B10000..U.2B10FFFF
c6ubokkw7#
代理对是UTF-16中的两个“代码单元”,它们组成一个“代码点”。Java文档指出,这些“代码点”在颠倒后仍然有效,它们的“代码单元”顺序正确。它进一步指出,两个不成对的代理代码单元可以颠倒并形成一个有效的代理对。这意味着如果存在不成对的代码单元,那么就有可能反向的反向可能不一样!但是请注意,文档中没有提到字形--它是多个码点的组合。这意味着e和与它一起沿着的重音仍然可以交换,因此重音放在e之前。这意味着如果e之前有另一个元音,它可能会得到e上的重音。哎呀!
7条答案
按热度按时间jum4pzuy1#
术语“代理项对”是指在UTF-16编码方案中使用高码位编码Unicode字符的方法。
在Unicode字符编码中,字符Map到0x 0和0x 10 FFFF之间的值。
在内部,Java使用UTF-16编码方案来存储Unicode文本的字符串。在UTF-16中,使用16位(两字节)代码单元。由于16位只能包含从0x 0到0xFFFF的字符范围,因此使用一些额外的复杂性来存储此范围(0x 10000到0x 10 FFFF)以上的值。这使用称为代理的代码单元对来完成。
代理代码单元在称为“高代理”和“低代理”的两个范围内,这取决于它们是否被允许在双代码单元序列的开始或结束处。
tnkciper2#
早期的Java版本使用16位的char数据类型表示Unicode字符。这种设计在当时是有意义的,因为所有Unicode字符的值都小于65,535(0xFFFF),可以用16位表示。然而,后来Unicode将最大值增加到1,114,111(0x 10 FFFF)。由于16位值太小,无法表示Unicode 3.1版中的所有Unicode字符,UTF-32编码方案采用了32位值(称为代码点)。但为了有效使用内存,16位值优于32位值,因此Unicode引入了一种新的设计,允许继续使用16位值。这种设计在UTF-16编码方案中采用,将1,024个值分配给16位高的代理(在U+D800到U+DBFF范围内)和另外1,024个值到16位低位替代值(在U+ DC 00到U+DFFF的范围内)。它使用一个高代理项,后面跟着一个低代理项(一个代理项对)来表示(1,024和1,024的乘积)1,048,576(0x 100000)个介于65,536(0x 10000)和1,114,111(0x 10 FFFF)之间的值。
qfe3c7zg3#
添加一些更多的信息,以上述答案从this后。
在Java-12中测试,应该可以在所有Java版本5以上工作。
如前所述:https://stackoverflow.com/a/47505451/2987755,
任何字符(其Unicode高于U+FFFF)都表示为代理对,Java将其存储为一对char值,即单个Unicode字符表示为两个相邻的Java字符。
正如我们可以在下面的例子中看到的。
1.长度:
字符串
1.平等:
使用Unicode
\ud83c\udf09
将“”表示为String,如下所示,并检查相等性。型
Java不支持UTF-32
型
1.您可以将Unicode字符转换为Java字符串
型
型
为了解决这个问题,我们可以使用
String.offsetByCodePoints(int index, int codePointOffset)
型
1.使用BreakIterator迭代Unicode字符串
1.使用Unicode java.text.Collator排序字符串
1.不应使用Character的
toUpperCase()
、toLowerCase()
方法,而应使用特定区域设置的String String和String。Character.isLetter(char ch)
不支持,最好使用Character.isLetter(int codePoint)
,对于Character类中的每个methodName(char ch)
方法,都会有methodName(int codePoint)
类型可以处理补充字符。1.指定
String.getBytes()
中的字符集,从字符串转换为字符串,InputStreamReader
,OutputStreamWriter
1.Java-21,
java.lang.Character.isEmoji
和新的Regex相关模式中添加了新方法,来自here的emoji数据,如果您正在使用here提到的任何库,此新功能可能会有所帮助型
参考号:
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
更多关于image1image2的信息
其他值得探讨的术语:标准化,BiDi
ioekq8ef4#
该文档的意思是,无效的UTF-16字符串在调用
reverse
方法后可能会变为有效,因为它们可能是有效字符串的反转。代理项对(这里讨论)是一对UTF-16中的16位值,它们编码单个Unicode代码点;低代理项和高代理项是该编码的两部分。kkbh8khc5#
小序
问题
该联盟认为16位将足以覆盖任何人类可读的语言,它给出了 2^16 = 65536 可能的代码值。这对于平面0来说是正确的,也被称为BMP或基本多语言平面,它包括今天65536个代码点中的55,445个。BMP几乎覆盖了世界上所有的人类语言,包括中国-日本-韩国符号(CJK)。
随着时间的推移,新的亚洲字符集被添加进来,仅中文符号就占据了70,000多个点。现在,甚至有Emoji points作为标准的Emoji points的一部分。新的16个“额外”Planes被添加进来。UCS-2房间不足以覆盖比Plane-0更大的东西。
Unicode决定
1.将Unicode限制为17个平面×每个平面65 536个字符= 1 114 112个最大点。
1.目前的UTF-32,以前称为UCS-4,为每个代码点保存32位,并覆盖所有平面。
1.继续使用UTF-8作为动态编码,将每个码点的UTF-8限制为最大4字节,即每个码点从1字节到4字节。
1.弃用UCS-2
1.基于UCS-2创建UTF-16。将UTF-16设置为动态的,因此每个点占用2个字节或4个字节。将1024个点U+D800-U+DBFF(称为高位替代)分配给UTF-16;将1024个符号U+ DC 00-U+DFFF(称为低位替代)分配给UTF-16。
通过这些变化,BMP被UTF-16中的1个16位块覆盖,而所有“补充字符”被代理对覆盖,每个代理对呈现2个16位块,总共1024 x1024 = 1 048 576点。
𝄞“MUSICAL SYMBOL G CLEF”,以UTF-16编码为一对代理0xD 834 0xDD 1 E(2 × 2字节),
在UTF-8中为0xF 0 0x 9D 0x 84 0x 9 E(4 × 1字节),
在UTF-32中为0x 0001 D11 E(1 × 4字节)。
目前情况
为了支持具有不正确的UTF-8/UTF-16编码的遗留应用程序,创建了一个新的标准WTF-8,即Wobbly Transformation Format。它支持任意代理点,例如非配对的代理或不正确的序列。今天,一些产品不符合该标准,并将UTF-8视为WTF-8。
许多历史细节被压制,以遵循主题。
最新的Unicode标准可以在http://www.unicode.org/versions/latest上找到
7gcisfzg6#
替代对指的是UTF-16编码某些字符的方式,请参阅http://en.wikipedia.org/wiki/UTF-16/UCS-2#Code_points_U.2B10000..U.2B10FFFF
c6ubokkw7#
代理对是UTF-16中的两个“代码单元”,它们组成一个“代码点”。Java文档指出,这些“代码点”在颠倒后仍然有效,它们的“代码单元”顺序正确。它进一步指出,两个不成对的代理代码单元可以颠倒并形成一个有效的代理对。这意味着如果存在不成对的代码单元,那么就有可能反向的反向可能不一样!
但是请注意,文档中没有提到字形--它是多个码点的组合。这意味着e和与它一起沿着的重音仍然可以交换,因此重音放在e之前。这意味着如果e之前有另一个元音,它可能会得到e上的重音。
哎呀!