2016-12-12 49 views
1

我正在編寫一些用於生成隨機字符串的代碼。結果字符串似乎包含無效的char組合。具體而言,我發現很高的代理人沒有跟隨低代理人。如何生成包含補充字符的隨機Unicode字符串?

任何人都可以解釋爲什麼發生這種情況?我是否必須明確地生成一個隨機低代理來跟隨高代理?我以爲這是不需要的,因爲我使用Character類的int變體。

這裏的測試代碼,這在最近的運行產生以下不好的配對:

 
Bad pairing: d928 - d863 
Bad pairing: da02 - 7bb6 
Bad pairing: dbbc - d85c 
Bad pairing: dbc6 - d85c 
public static void main(String[] args) { 
    Random r = new Random(); 
    StringBuilder builder = new StringBuilder(); 

    int count = 500; 
    while (count > 0) { 
    int codePoint = r.nextInt(Character.MAX_CODE_POINT + 1); 

    if (!Character.isDefined(codePoint) 
     || Character.getType(codePoint) == Character.PRIVATE_USE) { 
     continue; 
    } 

    builder.appendCodePoint(codePoint); 
    count--; 
    } 

    String result = builder.toString(); 

    // Test the result 
    char lastChar = 0; 
    for (int i = 0; i < result.length(); i++) { 
    char c = result.charAt(i); 
    if (Character.isHighSurrogate(lastChar) && !Character.isLowSurrogate(c)) { 
     System.out.println(String.format("Bad pairing: %s - %s", 
      Integer.toHexString(lastChar), Integer.toHexString(c))); 
    } 
    lastChar = c; 
    } 
} 
+0

Character.isDefined的代理人返回true。 – VGR

回答

1

這是可能的隨機生成高或低的替代物。如果這導致代理人低,或者代理人代替率低的代理人高,則結果字符串無效。該解決方案是簡單地排除所有代理人:

if (!Character.isDefined(codePoint) 
    || Character.isSurrogate(codePoint) 
    || Character.getType(codePoint) == Character.PRIVATE_USE) { 
    continue; 
} 

(從技術上講,你也可以允許隨機產生較高的代理人,並添加另一個隨機低位代理,但是這隻會造成其他隨機碼點> = 0x10000的可能反過來未定義或供私人使用。)

+0

isSurrogate需要一個字符,而不是代碼點。我不確定在這個階段是否真的安全。 – lhunath

1

你需要排除所有代理孤兒(即高代理和低代理的)。

僅供參考,從UnicodeData.txt顯示未來一段代碼點區間代理人:

D800;<Non Private Use High Surrogate, First>;Cs;0;L;;;;;N;;;;; 
DB7F;<Non Private Use High Surrogate, Last>;Cs;0;L;;;;;N;;;;; 
DB80;<Private Use High Surrogate, First>;Cs;0;L;;;;;N;;;;; 
DBFF;<Private Use High Surrogate, Last>;Cs;0;L;;;;;N;;;;; 
DC00;<Low Surrogate, First>;Cs;0;L;;;;;N;;;;; 
DFFF;<Low Surrogate, Last>;Cs;0;L;;;;;N;;;;;