我在JavaFX中从补充(“星体”)平面处理Unicode字符时遇到问题。具体来说,我不能在TextInputDialog
中粘贴这些字符(我得到一些奇怪的字符,例如ð
),并且不能在WebView中使用它们(它们被渲染为{{1 }})。
如果我通过������
输入它们并将它们打印到控制台,则相同的字符工作正常。它们甚至在JavaFX JOptionPane.showInputDialog
中显示,尽管它最后添加了一些垃圾。
有没有办法解决这些问题?
我在Linux中使用Oracle JDK版本1.8.0_51
补充平面字符的例子:
如果您看不到它们,则可能需要安装其他字体,例如Symbola或Noto。
以下是一个示例程序(使用Alert
而不是Label
):
WebView
以下是我得到的结果:
注意:并非示例中的所有字符都来自辅助平面,其中一个字符仅在控制台中正确呈现。
答案 0 :(得分:3)
以下是您正在使用的文字。
ಠñ
十进制代码点表示:
127137 178050 3232 128512 241
十六进制表示:
0x1F0A1 0x2B782 0xCA0 0x1F600 0xF1
Java在内部使用UTF-16。所以考虑UTF-16表示:
UTF-16表示:
D83C DCA1 D86D DF82 0CA0 D83D DE00 00F1
我们可以看到显示器显示了您期望的五个字符,但随后显示了三个垃圾字符。
所以它显然试图显示8个字形,其中只有5个。这几乎可以肯定,因为显示代码计数为8个字符,因为三个字符以UTF-16编码为代理对,因此每个字符取两个16位字。换句话说,在存在代理对的情况下,它使用了错误的字符串长度值。
UTF-8测试数据的表示:
F0 9F 82 A1 F0 AB 9E 82 E0 B2 A0 F0 9F 98 80 C3 B1
看到的是
00F0 ð LATIN SMALL LETTER ETH
009F <control> = APC = APPLICATION PROGRAM COMMAND
0082 <control> = BPH = BREAK PERMITTED HERE
00A1 ¡ INVERTED EXCLAMATION MARK
00F0 ð LATIN SMALL LETTER ETH
(两个控制字符在某些包含缩写或十六进制代码的字体中可以包含字形。这些字符在您的示例中可见。)
Latin1十六进制表示:
F0 9F 82 A1 F0
请注意,这五个字节与预期文本的UTF-8表示的前五个字节相同。
结论:粘贴的数据被粘贴为占用17个字节的5个UTF-8代码点,但被解释为占用5个字节的5个Latin1代码点。同样,错误的属性已被用于长度。
答案 1 :(得分:0)
此问题已在Java 10中解决。 参见Java Bug Report。