2012-12-10 51 views
5

我想要一個算法或庫,可以指示一個Unicode點是否有效。例如U+F8F8似乎不是一個有效的Unicode字符,但被描述爲"PRIVATE_USE_AREA"。我找到了ICU - 這是一個很好/最好的解決方案嗎?如何確定一個Unicode字符是否有效

UPDATE:@再編程的建議(下)是使用:

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)其是(I假定)僅當隨後在至少一個或多個碼點有效

UPDATE:@Jukka寫道:

定義「有效的」 A私人用途。代碼點根據Unicode 標準有效,它在 標準中沒有任何字符分配。代理代碼點不是有效的字符數據,但 替代代碼單元可用於UTF-16。 Java字符串是代碼單元的一個 序列,而不是字符;任何代碼單元可能在那裏出現 ,但是當您處理字符串作爲字符,它應該符合 Unicode字符的要求。 - Jukka K. Korpela

我同意定義「有效」很重要。我把從FileFormat.Info網站宣告用法:

U+F8F8 is not a valid unicode character. 

這似乎是一個相當權威的網站,所以我用自己的任期。也許他們有些不準確

更新: 我已經嘗試@伊格納西奧的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()); 
    } 

即使對於「有效的」Unicode字符,它也統一返回false。我也找不到\p{Cn}記錄。

+0

你有沒有試過CharsetCallback.Decoder http://icu-project.org/apiref/icu4j/com/ibm/icu/charset/CharsetCallback.Decoder.html? – reprogrammer

+0

定義「有效」。私人使用代碼點根據Unicode標準是有效的,它在標準中沒有任何字符分配給它。代理*代碼點*不是有效的字符數據,但代理*代碼單元*可以在UTF-16中使用。 Java字符串是一系列代碼單元,而不是字符;任何代碼單元都可能出現在那裏,但是當您將字符串作爲字符處理時,它應該符合Unicode對字符的要求。 –

+0

@Jukka這是非常有用的。已將其複製到文本中。 –

回答

3

的做法是,你在評論描述爲回答@ IgnacioVazquez-Abrams是一個正確的,使用匹配模式,如"\\p{Cn}",測試的一般類別(gc)屬性。但是對於U + F8F8,這個特定的匹配會產生錯誤,因爲這個角色的類別不是Cn而是Cs(其他代理)。如果你測試例如對於U + FFFF,你會變得真實。

Unicode的類別中的主要類C(與類別名稱爲C開始)爲:

  • 抄送:其他,控制;控制字符,例如回車
  • 參照:其他,格式;例如軟連字符(不可見的,但可能會影響格式化)
  • CS:其他,替代物;在字符數據無效,但可能會出現,成對,在Java字符串(這是代碼單元的字符串,而不是字符)
  • 有限公司:其他,私人使用;在字符數據中有效,但沒有Unicode標準分配的字符,除私人分配(指定代碼點的某些含義)外,不應將其用於信息交換中(爲代碼點分配一些含義)
  • Cn:其他,未分配;這可能意味着代碼點永久地表示爲非字符,或者只是未分配,例如,尚未分配(但可能被分配到未來版本的Unicode中的字符)

因此,在測試有效性時,應拒絕Cn Unicode標準被改變);在測試代​​碼點時應該拒絕Cs,但是在處理Java字符串時,如果第一個字符是高代理字符,第二個字符是低代理字符,則應該接受一對Cs字符(假設您希望接受基本多語言平面之外的字符);和處理Co取決於您是否希望將私人使用代碼點視爲有效。

例如,私人使用代碼點可能出現在意圖使用具有分配給這些代碼點的字形的字體顯示的數據中。這樣的字體很爛,但它們存在,並且這種方法在形式上不正確。

其他主要類中的Unicode代碼點將被視爲毫無疑問的字符。這並不意味着應用程序需要接受它們,只是它們有效地表示字符。

+0

謝謝。無法在Oracle Javadoc for 1.6 http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html中找到它,但可能沒有仔細閱讀它 –

0

與「Cn」Unicode屬性的匹配表示無效的Unicode字符。 Python中的一個例子(可以很容易地轉換爲Java):使用String.codePointAt
這裏

>>> 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> 
+0

這不是一個非常有用的回覆,因爲我不知道Python的「‘道道通’的Unicode財產」和(至少對我來說)它不能很容易地轉換爲Java,因爲我不理解的事。 「Cn」是定義Unicode的正則表達式庫嗎? –

+0

這不是Python的,它是[統一的](http://www.unicode.org/reports/tr44/tr44-4.html#Property_Values)。只需將其推入['Pattern'](http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html)。 –

+0

會試試看,感謝 –

2

嘗試是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. 
+0

這看起來很有用,我會試試看。 (爲便於閱讀而格式化) –

相關問題