3

以下 java 代码完全符合预期:

1      String s = "♪♬♪♪♬♪♪♬♪♪♬♪♪♬♪♪♬♪";
2      for(int i=0; i < s.length(); i++)
3      {
4         System.out.print(s.substring(i,i+1));
5         //System.out.print("\r");
6         Thread.currentThread().sleep(500);
7      }

但是当我尝试通过在第 5 行添加回车时,它会打印 ?s。为什么会这样,我将如何解决?

(我也尝试使用“\u240d”作为回车 - 同样的事情)。

编辑:输出到 Mac OS X 上的 bash。

4

3 回答 3

4

请同时打印 s.length(),我敢打赌它超过 18。java 字符串表示是 utf-16,String.substring 只是提取 char 值。音符从 0x1d000 开始 - 它们不适合单个字符。从字符串中提取完整的代码点/字形使用类似 icu 项目的东西 - UCharacterIterator

ps:我不知道您的终端会话是否可以显示这些字符

于 2009-11-20T09:11:42.813 回答
3

我希望这是由于您的终端如何解释输出。

正如上面所指出的,所有的音符字形都是多字节字符。此外,Javachar的宽度仅为 16 位,因此char单个字符本身无法可靠地表示单个 Unicode 字符——因此该String.substring方法并非完全对多字节友好。

因此,可能发生的情况是,在循环的每次迭代中,Java 都会打印出半个字符。当打印出一对的第一个字节时,终端意识到它是一个多字节字符的前半部分并且不显示它。当打印下一个字节时,终端看到该注释对应的完整字符并显示出来。

当您取消注释println("\r"), 时会发生什么是您在每个字符的两半中间插入一个换行符因此,终端永远不会得到代表音符的字节序列,例如 0x26、0x6C,而是得到 0x26、0x10、0x6C、0x10,因此不会呈现音符。

于 2009-11-20T09:26:56.947 回答
1

Java 不知道您的源文件是 UTF-8。

如果你编译

javac -encoding utf8 MyClass.java

并运行

java -Dfile.encoding=utf8 MyClass

它会起作用的。

(有人知道为什么 UTF-8 不是默认的吗?)

于 2009-11-20T10:09:21.307 回答