gpt4 book ai didi

java - 如何阅读非 BMP (astral) Unicode 增补字符(代码点)

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:37:38 25 4
gpt4 key购买 nike

G 谱号 (U+1D11E) 不属于 Basic Multilingual Plane (BMP),这意味着它需要超过 16 位。几乎所有 Java 的读取函数只返回一个 char 或一个 int 也包含 only 16 bit .哪个函数读取完整的 Unicode 符号,包括 SMP、SIP、TIP、SSP 和 PUA?

更新

我问过如何从输入流中读取单个 Unicode 符号(或代码点)。我既没有任何整数数组,也不想读取一行。

可以使用 Character.toCodePoint() 构建代码点,但此函数需要 char。另一方面,读取 char 是不可能的,因为 read() 返回一个 int。到目前为止,我最好的解决方法是这个,但它仍然包含不安全的转换:

public int read_code_point (Reader input) throws java.io.IOException
{
int ch16 = input.read();
if (Character.isHighSurrogate((char)ch16))
return Character.toCodePoint((char)ch16, (char)input.read());
else
return (int)ch16;
}

如何做得更好?

更新 2

另一个返回字符串但仍然使用强制转换的版本:

public String readchar (Reader input) throws java.io.IOException
{
int i16 = input.read(); // UTF-16 as int
if (i16 == -1) return null;
char c16 = (char)i16; // UTF-16
if (Character.isHighSurrogate(c16)) {
int low_i16 = input.read(); // low surrogate UTF-16 as int
if (low_i16 == -1)
throw new java.io.IOException ("Can not read low surrogate");
char low_c16 = (char)low_i16;
int codepoint = Character.toCodePoint(c16, low_c16);
return new String (Character.toChars(codepoint));
}
else
return Character.toString(c16);
}

剩下的问题:强制转换是否安全或如何避免?

最佳答案

My best work around so far is this but it still contains unsafe casts

您提供的代码唯一不安全的地方是,如果 input 已达到 EOF,则 ch16 可能为 -1。如果您首先检查此条件,那么您可以保证其他 (char) 转换是安全的,因为 Reader.read() is specified返回 -1 或 char (0 - 0xFFFF) 范围内的值。

public int read_code_point (Reader input) throws java.io.IOException
{
int ch16 = input.read();
if (ch16 < 0 || !Character.isHighSurrogate((char)ch16))
return ch16;
else {
int loSurr = input.read();
if(loSurr < 0 || !Character.isLowSurrogate((char)loSurr))
return ch16; // or possibly throw an exception
else
return Character.toCodePoint((char)ch16, (char)loSurr);
}
}

这仍然不理想,您确实需要处理边缘情况,即读取的第一个 char 是高代理项但第二个不是匹配的低代理项,在这种情况下您可能想按原样返回第一个 char 并备份 reader 以便下一次读取为您提供下一个字符。但这仅在 input.markSupported() == true 时有效。如果你可以保证那么怎么样

public int read_code_point (Reader input) throws java.io.IOException
{
int firstChar = input.read();
if (firstChar < 0 || !Character.isHighSurrogate((char)firstChar)) {
return firstChar;
} else {
input.mark(1);
int secondChar = input.read();
if(secondChar < 0) {
// reached EOF
return firstChar;
} else if(!Character.isLowSurrogate((char)secondChar)) {
// unpaired surrogates, un-read the second char
input.reset();
return firstChar;
}
else {
return Character.toCodePoint((char)firstChar, (char)secondChar);
}
}
}

或者您可以将原始阅读器包装在 PushbackReader 中并使用 unread(secondChar)

关于java - 如何阅读非 BMP (astral) Unicode 增补字符(代码点),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17361210/

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