Java中无法显示UTF-8 CJK字符

12

我已经研究了Unicode和UTF-8编码一段时间,我想我理解了它,所以希望这不是一个愚蠢的问题:

我有一个文件,其中包含一些CJK字符,并已保存为UTF-8。我安装了各种亚洲语言包,并且其他应用程序可以正确地呈现这些字符,所以我知道那部分是有效的。

在我的Java应用程序中,我按以下方式读取文件:

// Create objects
fis = new FileInputStream(new File("xyz.sgf"));
InputStreamReader is = new InputStreamReader(fis, Charset.forName("UTF-8"));
BufferedReader br = new BufferedReader(is);

// Read and display file contents
StringBuffer sb = new StringBuffer();
String line;
while ((line = br.readLine()) != null) {
    sb.append(line);
}
System.out.println(sb);

输出中显示的CJK字符为“???”。调用is.getEncoding()确认它确实在使用UTF-8。我错过了什么步骤才能使字符正确显示?如果有差异,我是在使用Eclipse控制台查看输出。


你正在使用哪个IDE(Netbeans,Eclipse等)? - Abdelwahed
1
我之前尝试了用阿拉伯字符,结果遇到了相同的问题。但是当我设置了断点并检查了字符串后,发现字符串正确地显示出来了。我将其打印到文件中,也是正常的。 - Abdelwahed
1
谢谢确认。进一步测试证实,问题只是我的Eclipse配置的问题。 - Twicetimes
4个回答

18
System.out.println(sb);

问题出在上面的那一行。这将使用默认的系统编码对字符数据进行编码,并将数据输出到STDOUT。在许多系统上,这是一个有损的过程。
如果您更改了默认设置,则System.out使用的编码和控制台使用的编码必须匹配。
更改默认系统编码的唯一支持机制是通过操作系统进行。 (有些人会建议使用file.encoding系统属性,但这是不受支持的,并且可能会产生意想不到的副作用。)您可以使用setOut将其设置为您自己的自定义PrintStream:
PrintStream stdout = new PrintStream(System.out, autoFlush, encoding);

你可以通过运行配置来更改Eclipse控制台的编码。 你可以在我的个人资料中找到关于这个主题的许多帖子。

1
非常有用,谢谢。不幸的是,由于我的声望还不够高,我无法为这个答案投票。 - Twicetimes
1
我已将运行配置更改为使用UTF-8,并按如下方式实现了自定义PrintStream:'PrintStream utfout = new PrintStream(System.out, false, "UTF-8"); System.setOut(utfout);',但字符仍然无法在Eclipse控制台窗口中正确显示。奇怪的是,它们从显示为“?”变成了一个方块,所以肯定发生了一些事情。只是不确定是什么。 - Twicetimes
2
@Twicetimes - 这样实际上更好,但这就是可能会变得棘手的地方。在我的系统上,尽管使用不支持中文字形的_Courier New_字体,但字体替换被用来呈现中文字符串。我相信Windows上的SWT使用了Uniscribe,所以您可能需要阅读Win32 API以了解这是如何发生的。您可能只是没有安装正确组合的字体。您可以切换字体到其中代码点被支持的字体。 - McDowell
1
谢谢。我刚试了几种不同的字体用于控制台输出,最终选择了“Lucida Sans Unicode”。我之前并没有意识到某些字体可能不包含某些表意文字,我一直以为这与编码有关。现在我明白了。 - Twicetimes

5
下面的程序使用TextPad将CJK字符打印到控制台。为了看到韩文和日文,我必须告诉Java更改打印流的编码为EUC_KR,并设置TextPad工具输出窗口的属性:
  • 字体是Arial Unicode MS
  • 脚本是Hangul

import java.io.PrintStream;
import java.io.UnsupportedEncodingException;

class Hangul {

    public static void main(String[] args)  throws Exception {

        // Change console encoding to Korean

        PrintStream out = new PrintStream(System.out, true, "EUC_KR");
        System.setOut(out);

        // Print sample to console

        String go_hello  = "가다 こんにちは";
        System.out.println(go_hello);
    }
}

Tool Output is:

가다 こんにちは


4

2

根据您所使用的平台,很可能您的控制台(或Windows CMD)不支持或使用UTF-8字符集,因此将所有无法映射的字符转换为问号。

例如,在Windows上,CMD几乎总是使用WIN1252或类似的单字节字符集。


是的,我不会期望Windows命令提示符正确显示它们,但我以为Eclipse会有。如果这确实是问题的根源,是否还有其他人可以验证Eclipse在控制台中无法正确显示某些Unicode字符?还有哪些地方可以显示程序的输出以测试其是否正常工作? - Twicetimes
1
@Twicetimes:将输出导入文件,并使用支持UTF-8的编辑器打开该文件。 - Christoffer Hammarström
@Christoffer Hammarström - 感谢您的建议。我使用指定了UTF-8字符集的OutputStreamWriter将字符串直接写回文件,并且在另一个应用程序中正确显示了字符,所以我想一切都很好。可能只是Eclipse控制台让我感到困惑。 - Twicetimes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接