繁体   English   中英

如何确定Unicode字符是否有效

[英]How to determine if a Unicode character is valid

我想要一个可以指示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.

谢谢。 这看起来比我希望的更复杂 - 也许这比我想象的更复杂。 (问题包括诸如'<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.

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

更新:我已经尝试了@ 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());
    }

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

您在@ 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字符,而第二个字符串是低代理字符串(假设您希望接受基本多语言平面之外的字符) ); 和Co的处理取决于您是否希望将私人使用代码点视为有效。

例如,私人使用代码点可能出现在旨在使用具有分配给这些代码点的字形的字体显示的数据中。 这些字体是kludgy,但它们存在,并且这种方法并非正式错误。

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

尝试使用String.codePointAt
这是API:

int java.lang.String.codePointAt(int index)



codePointAt
public int codePointAt(int index)
Returns the character (Unicode code point) at the specified index. 
   The index refers to char values (Unicode code units) and ranges from 0 to length() - 1. 
If the char value specified at the given index is in the high-surrogate range, the 
    following index is less than the length of this String, and the char value at the 
    following index is in the low-surrogate range, then the supplementary code point 
    corresponding to this surrogate pair is returned. Otherwise, the char value at the
    given index is returned. 


Parameters:
index - the index to the char values 
Returns:
the code point value of the character at the index 
Throws: 
IndexOutOfBoundsException - if the index argument is negative or not less than the 
    length of this string.

与“Cn”Unicode属性匹配表示Unicode字符无效。 Python中的一个例子(可以很容易地转换为Java):

>>> regex.match(r'\p{Cn}', u'\ud800')
<_regex.Match object at 0x7f6d5552c120>
>>> regex.match(r'\p{Cn}', u'a')
>>> regex.match(r'\p{Cn}', u'\uf8f8')
<_regex.Match object at 0x7f6d5552c198>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM