2016-12-12 50 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;;;;;