首页 > 解决方案 > 如何从变量中的 id 获取 unicode 字符?

问题描述

我正在尝试使用每个 Unicode 变量生成一个文件。我已经能够将 unicode 提升到 U+FFFF,但是我需要将它提升到 U+231F4。我试过寻找答案,但是当符号 id 在变量中而不是仅仅输入时,它们都不起作用。

现在,我有这个:

for (int i = 0; i < 143860; i++) {
            System.out.println((char)i);
        }

它不是上升到 U+231F4,而是上升到 U+FFFF,并在它正在打印的文档中循环。如何使它转到更高的 Unicode ID?

标签: javaunicode

解决方案


[ OP 说“我需要把它升级到 U+231F4 ”,我回答了这个问题。但他们的意思是他们想要打印 Unicode 定义的 143,859 个代码点。看另一个答案。我现在不能删除它,因为它已被接受。]

Java 字符串不是由 Unicode 代码点构成,而是由 UTF-16 代码单元构成。对于 U+FFFF 以上的 Unicode 代码点,您需要使用代理对。例如,

     U+0   ⇒   0x0000            ⎫
     U+1   ⇒   0x0001            ⎪
           ⋮                      ⎬ Character in the BMP result
  U+D7FE   ⇒   0xD7FE            ⎪   in a single UTF-16 code unit.
  U+D7FF   ⇒   0xD7FF            ⎭

  U+D800   ⇒   ------            ⎫
  U+D801   ⇒   ------            ⎪
           ⋮                      ⎬ Can't be encoded using UTF-16.
  U+DFFE   ⇒   ------            ⎪   Illegal for interchange for this reason.
  U+DFFF   ⇒   ------            ⎭

  U+E000   ⇒   0xE000            ⎫
  U+E001   ⇒   0xE001            ⎪
           ⋮                      ⎬ Character in the BMP result
  U+FFFE   ⇒   0xFFFE            ⎪   in a single UTF-16 code unit.
  U+FFFF   ⇒   0xFFFF            ⎭

 U+10000   ⇒   0xD800, 0xDC00    ⎫
 U+10001   ⇒   0xD800, 0xDC01    ⎪
           ⋮                      ⎬ Those outside result in two.
 U+231F2   ⇒   0xD84C, 0xDDF2    ⎪
 U+231F3   ⇒   0xD84C, 0xDDF3    ⎭

 U+231F4   ⇒   0xD84C, 0xDDF4    ⎫
 U+231F5   ⇒   0xD84C, 0xDDF5    ⎪
           ⋮                      ⎬ We don't care about these.
U+10FFFE   ⇒   0xDBFF, 0xDFFE    ⎪
U+10FFFF   ⇒   0xDBFF, 0xDFFF    ⎭

有关代理对的详细信息,您可以查阅UTF-16的 Wikipedia 页面。

解决方案1:printf %c

这些细节无关紧要,因为我们可以使用printf %c将 Unicode 代码点编码为 UTF-16 代码单元。(感谢@VGR。)

for (int cp=0; cp<0x231F4; ++cp) {
   if (cp < 0xD800 || cp >= 0xE000) {
      System.out.printf("%c%n", cp);
   }
}

优化:

for (int cp=0; cp<0xD800; ++cp) {
   System.out.println((char)cp);
}

for (int cp=0xE000; cp<0x10000; ++cp) {
   System.out.println((char)cp);
}

for (int cp=0x10000; cp<0x231F4; ++cp) {
   System.out.printf("%c%n", cp);
}

解决方案2:Character.toChars

或者,我们可以使用Character.toChars(codePoint)生成一个char[]包含 UTF-16 代码单元的 Unicode 代码点。

for (int cp=0; cp<0x231F4; ++cp) {
   if (cp < 0xD800 || cp >= 0xE000) {
      System.out.println(Character.toChars(cp));
   }
}

优化:

for (int cp=0; cp<0xD800; ++cp) {
   System.out.println((char)cp);
}

for (int cp=0xE000; cp<0x10000; ++cp) {
   System.out.println((char)cp);
}

for (int cp=0x10000; cp<0x231F4; ++cp) {
   System.out.println(Character.toChars(cp));
}

我相信上面仍然会创建很多数组。自己实现转换可以避免这种情况,因此应该更快。

// Up to but excluding U+231F4 ⇒ 0xD84C, 0xDDF4

for (int cp=0; cp<0xD800; ++cp) {
   System.out.println((char)cp);
}

for (int cp=0xE000; cp<0x10000; ++cp) {
   System.out.println((char)cp);
}

char pair[2];
for (int hisurro=0xD800; hisurro<0xD84C; ++hisurro) 
   pair[0] = (char)hisurro;
   for (int losurro=0xDC00; losurro<0xE000; ++losurro) 
      pair[1] = (char)losurro;
      System.out.println(pair);
   }
}

pair[0] = 0xD84C;
for (int losurro=0xDC00; losurro<0xDDF4; ++losurro) 
   pair[1] = (char)losurro;
   System.out.println(pair);
}

请注意,结果在您的终端中不会完全可读。输出包括不可打印字符(例如控制字符)、标记(与其他字符组合)、未分配的代码点、私人使用的代码点等。


推荐阅读