【问题标题】:Java reading in character streams with supplementary unicode charactersJava 读取带有补充 unicode 字符的字符流
【发布时间】:2013-05-31 18:44:38
【问题描述】:

我在使用 Java 读取补充 unicode 字符时遇到问题。我有一个文件可能包含补充集中的字符(大于 \uFFFF 的任何字符)。当我设置 InputStreamReader 以使用 UTF-8 读取文件时,我希望 read() 方法为每个补充字符返回一个字符,而不是它似乎在 16 位阈值上拆分。

我看到了一些关于基本 unicode 字符流的其他问题,但似乎没有任何东西可以处理大于 16 位的情况。

下面是一些简化的示例代码:

InputStreamReader input = new InputStreamReader(file, "UTF8");
int nextChar = input.read();
while(nextChar != -1) {
    ...
    nextChar = input.read();
}

有谁知道我需要做什么才能正确读取包含补充字符的 UTF-8 编码文件?

【问题讨论】:

    标签: java unicode astral-plane supplementary


    【解决方案1】:

    Java 与 UTF-16 一起使用。因此,如果您的输入流具有星体字符,它们将显示为代理对,即两个chars。第一个字符是高代理,第二个字符是低代理。

    【讨论】:

    • 这是有道理的。有没有一种简单的方法来判断一个角色是否是代理对中的第一个?
    • 当然,使用Character.isHighSurrogate()。 (代理对的后半部分还有Character.isLowSurrogate()。)
    • 或者,如果您知道构成代理对的第一个字符的索引,请使用 String.codePointAt() / Character.codePointAt() 方法。
    • 看起来很有效。最后一个问题...我有一个使用 unicode 字符类(例如“\p{Nd}”)的正则表达式,这些类似乎不适用于这些代理对。有没有简单的解决方案?
    • 这里有一个链接,详细讨论了 Java 中补充字符和代理代码点的编码:ibm.com/developerworks/java/library/j-unicode
    【解决方案2】:

    虽然read() 被定义为返回int,并且理论上可以“一次性”返回一个补充字符的代码点,但我相信返回类型只有int 允许返回值-1 .

    您从read() 获得的值基本上是另一个名称的char,而Java 的char 限制为16 位。

    Java 只能将补充字符表示为 UTF-16 代理对,就 Java 而言,一旦超过 0xFFFF,就没有“单个字符”(至少在 char 意义上)这样的东西。

    【讨论】:

    • 虽然 JDK 确实公开了“代码点”的概念,它是从 UCS-2 (~= UTF-16) 字符解码出来的 32 位完整 unicode 值,但大多数情况下是正确的。因此,虽然 char 被限制为 16 位,但 Java 并没有忘记 Unicode 代码点超出 16 位这一事实。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-29
    • 2012-12-02
    • 2018-11-18
    • 1970-01-01
    • 2011-12-25
    • 1970-01-01
    相关资源
    最近更新 更多