如何确定Unicode字符是否有效

pet*_*ust 6 java unicode internationalization icu

我想要一个可以指示Unicode点是否有效的算法或库.例如,U+F8F8似乎不是有效的Unicode字符,但被描述为"PRIVATE_USE_AREA".我找到了ICU - 这是一个好/最好的解决方案吗?

更新:@Reprogrammer的建议(如下)是使用:

CoderResult call(CharsetDecoderICU decoder, Object context, 
     ByteBuffer source, CharBuffer target, IntBuffer offsets, 
     char[] buffer, int length, CoderResult cr)
This function is called when the bytes in the source cannot be handled, 
    and this function is meant to handle or fix the error if possible.
Run Code Online (Sandbox Code Playgroud)

谢谢.这看起来比我希望的更复杂 - 也许这比我想象的更复杂.(问题包括诸如'<Non Private Use High Surrogate, First>' (U+D800)(我假设)仅在有至少一个代码点后才有效的点.

更新:@Jukka写道:

定义"有效".私有代码点根据Unicode标准有效,它在标准中没有分配任何字符.代理代码点不是有效的字符数据,但代理代码单元可以在UTF-16中使用.Java字符串是一系列代码单元,而不是字符; 任何代码单元都可能出现在那里,但是当您将字符串作为字符处理时,它应符合Unicode对字符的要求. - Jukka K. Korpela

我同意定义"有效"很重要.我从FileFormat.Info站点获取了使用声明:

 U+F8F8 is not a valid unicode character.
Run Code Online (Sandbox Code Playgroud)

它似乎是一个相当权威的网站,所以我使用他们的术语.也许他们有点不精确

更新:我已经尝试了@ Ignacio的Python到Java但是失败了.我写

public void testUnicode() {
        Pattern pattern = Pattern.compile("\\p{Cn}");
        System.out.println("\\u0020 "+pattern.matcher("\u0020").matches());
        System.out.println("A "+pattern.matcher("A").matches());
        System.out.println("\\uf8f8 "+pattern.matcher("\uf8f8").matches());
    }
Run Code Online (Sandbox Code Playgroud)

统一返回false,即使是"有效"的Unicode字符.我也找不到\p{Cn}记录.

Juk*_*ela 5

您在@IgnacioVazquez-Abrams 对答案的评论中描述的方法是正确的方法,它使用与模式匹配"\\p{Cn}",例如测试通用类别 (gc) 属性。但对于 U+F8F8,此特定匹配正确地产生错误,因为此字符的类别不是 Cn 而是 Cs(其他,代理)。如果您测试例如 U+FFFF,您会得到正确的结果。

主要类别 C 中的 Unicode 类别(类别名称以 C 开头)是:

  • 抄送:其他,控制;控制字符,例如回车
  • Cf:其他,格式;例如软连字符(不可见,但可能会影响格式)
  • Cs:其他,代理人;在字符数据中无效,但可以成对出现在 Java 字符串(它是代码单元的字符串,而不是字符)中
  • Co:其他,私人使用;在字符数据中有效,但没有被 Unicode 标准分配给它的字符,除了私有分配(为代码点分配一些含义)外,不应在信息交换中使用
  • Cn:其他,未分配;这可能意味着代码点永久表示为非字符,或者只是未分配,例如尚未分配(但可能会分配给未来版本的 Unicode 中的字符)

所以在测试有效性时,应该拒绝 Cn(保留这可能会导致在 Unicode 标准改变时拒绝有效字符);测试代码点时应该拒绝Cs,但是在处理Java字符串时,当第一个是高代理而第二个是低代理时,您应该接受一对Cs字符(假设您希望接受Basic Multilingual Plane之外的字符); Co 的处理取决于您是否希望将 Private Use 代码点视为有效。

例如,私有使用代码点可能出现在旨在使用具有分配给此类代码点的字形的字体显示的数据中。这种字体很笨拙,但它们确实存在,而且这种方法在形式上并没有错。

其他主要类别中的 Unicode 代码点将被视为毫无疑问的字符。这并不意味着应用程序需要接受它们,只是它们有效地表示字符。