Cra*_*tis 6 java character emoji grapheme
我正在计算提供的Java字符串中可感知的表情符号字符的数量。我目前正在使用emoji4j库,但不适用于像这样的字素簇:???
调用EmojiUtil.getLength("???")return 4代替1,类似地调用EmojiUtil.getLength("???")return 5代替2。
StringJava中是否有任何API或方法可以简化字素簇的计数?
我一直在寻找,但可以理解的是codePoints(),a上的方法String不仅包括可见的表情符号,还包括零宽度的连接符。
我也尝试使用BreakIterator:
public static int getLength(String emoji) {
BreakIterator it = BreakIterator.getCharacterInstance();
it.setText(emoji);
int emojiCount = 0;
while (it.next() != BreakIterator.DONE) {
emojiCount++;
}
return emojiCount;
}
Run Code Online (Sandbox Code Playgroud)
但是它的行为似乎与codePoints()方法相同,返回8类似的东西"???"。
在提出这个问题六年多后,String几周前发布的 Java 20 中终于实现了在 a 中正确处理字素簇的增强功能。请参阅BreakIterator 中的 JDK-8291660 Grapheme 支持。
BreakIterator 类的 API 没有变化,但其底层代码现在正确地将字素簇视为单个单元而不是多个字符。
\n这是一个示例应用程序,使用问题中提供的方法和数据,没有任何更改:
\nimport java.nio.charset.Charset;\nimport java.text.BreakIterator;\n\npublic class Main {\n\n public static void main(String[] args) throws java.io.UnsupportedEncodingException {\n System.out.println("System.getProperty(\\"java.version\\"): " + System.getProperty("java.version"));\n System.out.println("Charset.defaultCharset():" + Charset.defaultCharset());\n Main.printStringInfo("\xe2\x80\x8d\xe2\x80\x8d\xe2\x80\x8d");\n Main.printStringInfo("\xe2\x80\x8d\xe2\x80\x8d\xe2\x80\x8d");\n }\n\n static void printStringInfo(String s) {\n System.out.print("\\nCode points for the String " + s + ":");\n s.codePoints().mapToObj(Integer::toHexString).forEach(x -> System.out.print(x + " "));\n System.out.println("\\nThe length of the String " + s + " using String.length() is " + s.length());\n System.out.println("The length of the String " + s + " using BreakIterator is " + Main.getLength(s));\n }\n\n // Returns the correct number of perceived characters in a String.\n // Requires JDK 20+ to work correctly.\n // Earlier Java releases will incorrectly just count the code points instead.\n // JDK-8291660 "Grapheme support in BreakIterator" (https://bugs.openjdk.org/browse/JDK-8291660) refers.\n public static int getLength(String emoji) {\n BreakIterator it = BreakIterator.getCharacterInstance();\n it.setText(emoji);\n int count = 0;\n while (it.next() != BreakIterator.DONE) {\n count++;\n }\n return count;\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n以下是输出,显示使用 JDK 20 时正确的字素计数(1 和 2):
\nC:\\Java\\jdk-20\\bin\\java.exe -javaagent:C:\\Users\\johndoe\\AppData\\Local\\JetBrains\\Toolbox\\apps\\IDEA-U\\ch-0\\232.5150.116\\lib\\idea_rt.jar=53642:C:\\Users\\johndoe\\AppData\\Local\\JetBrains\\Toolbox\\apps\\IDEA-U\\ch-0\\232.5150.116\\bin -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 -classpath D:\\II2023.1\\Graphemes\\out\\production\\Graphemes Main\nSystem.getProperty("java.version"): 20-ea\nCharset.defaultCharset():UTF-8\n\nCode points for the String \xe2\x80\x8d\xe2\x80\x8d\xe2\x80\x8d:1f469 200d 1f469 200d 1f466 200d 1f466 \nThe length of the String \xe2\x80\x8d\xe2\x80\x8d\xe2\x80\x8d using String.length() is 11\nThe length of the String \xe2\x80\x8d\xe2\x80\x8d\xe2\x80\x8d using BreakIterator is 1\n\nCode points for the String \xe2\x80\x8d\xe2\x80\x8d\xe2\x80\x8d:1f47b 1f469 200d 1f469 200d 1f466 200d 1f466 \nThe length of the String \xe2\x80\x8d\xe2\x80\x8d\xe2\x80\x8d using String.length() is 13\nThe length of the String \xe2\x80\x8d\xe2\x80\x8d\xe2\x80\x8d using BreakIterator is 2\n\nProcess finished with exit code 0\nRun Code Online (Sandbox Code Playgroud)\n以下是相同代码的输出,显示使用 JDK 17 时不正确的字素计数(7 和 8):
\nC:\\Java\\jdk-17.0.2\\bin\\java.exe -javaagent:C:\\Users\\johndoe\\AppData\\Local\\JetBrains\\Toolbox\\apps\\IDEA-U\\ch-0\\232.5150.116\\lib\\idea_rt.jar=53775:C:\\Users\\johndoe\\AppData\\Local\\JetBrains\\Toolbox\\apps\\IDEA-U\\ch-0\\232.5150.116\\bin -Dfile.encoding=UTF-8 -classpath D:\\II2023.1\\Graphemes\\out\\production\\Graphemes Main\nSystem.getProperty("java.version"): 17.0.2\nCharset.defaultCharset():UTF-8\n\nCode points for the String \xe2\x80\x8d\xe2\x80\x8d\xe2\x80\x8d:1f469 200d 1f469 200d 1f466 200d 1f466 \nThe length of the String \xe2\x80\x8d\xe2\x80\x8d\xe2\x80\x8d using String.length() is 11\nThe length of the String \xe2\x80\x8d\xe2\x80\x8d\xe2\x80\x8d using BreakIterator is 7\n\nCode points for the String \xe2\x80\x8d\xe2\x80\x8d\xe2\x80\x8d:1f47b 1f469 200d 1f469 200d 1f466 200d 1f466 \nThe length of the String \xe2\x80\x8d\xe2\x80\x8d\xe2\x80\x8d using String.length() is 13\nThe length of the String \xe2\x80\x8d\xe2\x80\x8d\xe2\x80\x8d using BreakIterator is 8\n\nProcess finished with exit code 0\nRun Code Online (Sandbox Code Playgroud)\n我使用Oracle OpenJDK 版本 20.0.1和Oracle OpenJDK 版本 17.0.2在Intellij IDEA 2023.1.1 Preview中对此进行了测试
\n| 归档时间: |
|
| 查看次数: |
1192 次 |
| 最近记录: |