gpt4 book ai didi

java - JavaFX 中的 Unicode 补充平面

转载 作者:搜寻专家 更新时间:2023-10-31 20:18:20 27 4
gpt4 key购买 nike

我在处理来自 JavaFX 补充(“astral”)平面的 Unicode 字符时遇到问题。具体来说,我不能将这些字符粘贴到 TextInputDialog 中(我得到一些奇怪的字符,例如 ð),也不能在 WebView 中使用它们(它们呈现为 ������).

如果我通过 JOptionPane.showInputDialog 输入相同的字符并将它们打印到控制台,则它们可以正常工作。它们甚至显示在 JavaFX Alert 中,尽管它在末尾附加了一些垃圾。

有没有办法解决这些问题?

我在 Linux 中使用 Oracle JDK 版本 1.8.0_51。
补充平面字符示例:😀𐂃🂡🙭𫞂
如果看不到它们,您可能需要安装其他字体,例如 Symbola 或 Noto。

这是一个示例程序(使用 Label 而不是 WebView):

import javax.swing.JOptionPane;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Label;
import javafx.scene.control.TextInputDialog;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class UniTest extends Application {
@Override
public void start(final Stage stage) throws Exception {
final String s = new String(new int[]{127137, 178050, 3232, 128512, 241}, 0, 5);
System.out.println("The string: " + s);
System.out.println("Characters: " + s.length());
System.out.println("Code points: " + s.codePoints().count());

JOptionPane.showMessageDialog(null, s, "JOptionPane", JOptionPane.INFORMATION_MESSAGE);

final Alert al = new Alert(AlertType.INFORMATION);
al.setTitle("Alert");
al.setContentText(s);
al.showAndWait();

final TextInputDialog dlg = new TextInputDialog();
dlg.setTitle("TextInputDialog");
dlg.setContentText("Try to paste the string in here");
dlg.showAndWait().ifPresent(x -> System.out.println("Your input: " + x));

final StackPane root = new StackPane();
root.getChildren().add(new Label(s));
stage.setScene(new Scene(root, 400, 300));
stage.setTitle("Stage");
stage.show();
}

public static void main(final String... args) {
launch(args);
}
}

这是我得到的结果:

screenshots

注意:并非示例中的所有字符都来自辅助平面,其中一个字符仅在控制台中正确呈现。

最佳答案

TL;DR:显然 JavaFX 有问题。

这是您正在使用的文本。

🂡𫞂ಠ😀ñ

十进制代码点表示:

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 个字形,而实际上只有五个。这几乎可以肯定是因为显示代码正在计算 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代码点。同样,长度使用了错误的属性。

关于java - JavaFX 中的 Unicode 补充平面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33107067/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com