为什么添加回车时stdout解码失败?

时间:2009-11-20 07:13:35

标签: java utf-8 special-characters decoding

以下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行的评论来添加回车时它会打印吗? 为什么会这样,我将如何解决?

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

编辑:输出在Mac OS X上进行重击。

3 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分:3)

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

如上所述,所有音符字形都是多字节字符。此外,Java char只有16位宽,因此单个char无法可靠地单独表示单个Unicode字符 - 随后String.substring方法不完全是多字节友好的。

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

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

答案 2 :(得分:1)

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

如果使用

进行编译
javac -encoding utf8 MyClass.java

并使用

运行
java -Dfile.encoding=utf8 MyClass

它会起作用。

(有谁知道为什么UTF-8不是默认值?)