如何生成包含增补字符的随机Unicode字符串?

时间:2016-12-12 21:28:44

标签: java unicode surrogate-pairs

我正在研究一些用于生成随机字符串的代码。生成的字符串似乎包含无效的char组合。具体而言,我发现高代理人没有低代理人。

任何人都可以解释为什么会这样吗?我是否必须明确生成随机低代理以遵循高代理人?我假设这不是必需的,因为我使用int类的Character变体。

这是测试代码,在最近的运行中产生了以下不良配对:

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;
  }
}

2 个答案:

答案 0 :(得分:1)

可以随机生成高或低代理。如果这导致低代理,或高代理没有低代理,则结果字符串无效。解决方案是简单地排除所有代理人:

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

(从技术上讲,你也可以允许随机生成的高代理并添加另一个随机的低代理,但这只会创建其他随机代码点&gt; = 0x10000,这可能会被取消定义或供私人使用。)

答案 1 :(得分: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;;;;;