【问题标题】:Java's charsets / character encodingJava的字符集/字符编码
【发布时间】:2012-11-09 20:40:20
【问题描述】:

我有一个西班牙文文件,里面充满了如下字符:

 á é í ó ú ñ Ñ Á É Í Ó Ú 

我必须阅读文件,所以我这样做:

fr = new FileReader(ficheroEntrada);
BufferedReader rEntrada = new BufferedReader(fr);

String linea = rEntrada.readLine();
if (linea == null) {
logger.error("ERROR: Empty file.");
return null;
} 
String delimitador = "[;]";
String[] tokens = null;

List<String> token = new ArrayList<String>();
while ((linea = rEntrada.readLine()) != null) {
    // Some parsing specific to my file. 
    tokens = linea.split(delimitador);
    token.add(tokens[0]);
    token.add(tokens[1]);
}
logger.info("List of tokens: " + token);
return token;

当我阅读标记列表时,所有特殊字符都消失了,并被这种字符取代:

Ó = Ó
Ñ = Ñ

等等……

发生了什么事?我从来没有遇到过字符集问题(我假设是字符集问题)。是因为这台电脑吗?我能做些什么?

任何额外的建议将不胜感激,我正在学习!谢谢!

【问题讨论】:

  • 使用InputStreamReader 并指定适当的编码。 FileReader 将采用“默认”编码,因此无法正确解码字符。

标签: java character-encoding non-ascii-characters


【解决方案1】:

需要指定相关的字符编码。

BufferedReader rEntrada  = new BufferedReader(
    new InputStreamReader(new FileInputStream(fr), "UTF-8"));

【讨论】:

    【解决方案2】:

    发生了什么事?

    建议使用 UTF-8 编码进行读写的答案应该可以解决您的问题。我的回答更多是关于发生了什么以及将来如何诊断类似问题。

    首先要从http://www.utf8-chartable.de 处的UTF-8 字符表开始。页面上有一个下拉菜单,可让您浏览 Unicode 的不同部分。你的问题人物之一是Ó。检查图表显示,如果您的文件以 UTF-8 编码,则字符为 U+00D3 LATIN CAPITAL LETTER O WITH ACUTE,而 UTF-8 序列为两个字节,十六进制 c3 93

    现在让我们检查http://en.wikipedia.org/wiki/ISO/IEC_8859-1 处的 ISO-8859-1 字符集,因为这也是一个流行的字符集。然而,这是那些单字节字符集之一。每个有效字符都由一个字节表示,这与 UTF-8 不同,其中一个字符可以由 1、2 或 3 个字节表示。

    请注意,C3 处的字符看起来像 Ã,但 93 处没有字符。所以您的默认编码可能不是 ISO-8859-1。

    接下来让我们在http://en.wikipedia.org/wiki/Windows-1252 检查Windows 1252。这与 ISO-8859-1 几乎相同,但用有用的字符填充了一些空白。我们有一场比赛。 Windows 1252中的序列C3 93正是字符串Ó

    这一切告诉我的是,您的文件是 UTF-8 编码的,但是您的 Java 环境配置为使用 Windows 1252 作为默认编码。如果您修改代码以显式指定字符集(“UTF-8”)而不是使用默认值,您的代码在不同环境中失败的可能性就会降低。

    但请记住 - 这也可能以另一种方式轻松发生。如果您有一个主要是西班牙语文本的文件,它可以很容易地成为 ISO-8859-1 或 Windows 1252 编码文件。在这种情况下,您的机器上运行的代码本来可以正常工作,但将其切换为“UTF-8”编码会产生一组不同的乱码。

    这是您收到相互矛盾的建议的部分原因。不同的人根据他们的平台遇到了不同的不匹配,因此发现了不同的修复方法。

    如果有疑问,我会在 emacs 中读取文件并切换到 hexl 模式,以便在文件中看到确切的二进制数据。我确信有更好、更现代的方法来做到这一点。

    最后的想法 - 可能值得一读 The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!

    【讨论】:

    • +1。背景信息很好。我建议标记为 Wiki。
    【解决方案3】:

    您的默认编码错误。您可能需要阅读 UTF8 或 latin1。请参阅此 sn-p 以设置流的编码。另见Java, default encoding

    public class Program {
    
        public static void main(String... args)  {
    
            if (args.length != 2) {
                return ;
            }
    
            try {
                Reader reader = new InputStreamReader(
                            new FileInputStream(args[0]),"UTF-8");
                BufferedReader fin = new BufferedReader(reader);
                Writer writer = new OutputStreamWriter(
                           new FileOutputStream(args[1]), "UTF-8");
                BufferedWriter fout = new BufferedWriter(writer);
                String s;
                while ((s=fin.readLine())!=null) {
                    fout.write(s);
                    fout.newLine();
                }
    
                //Remember to call close. 
                //calling close on a BufferedReader/BufferedWriter 
                // will automatically call close on its underlying stream 
                fin.close();
                fout.close();
    
            } catch (IOException e) {
                e.printStackTrace();
            }
    
        }
    }
    

    【讨论】:

      【解决方案4】:

      根据我的经验,文本文件的读写应该基于西方编码:ISO-8859-1。

      BufferedReader rEntrada = new BufferedReader( new InputStreamReader(new FileInputStream(fr), "ISO-8859-1"));

      【讨论】:

      • 我的文档中有 áéíóú 字符,这种编码对我有用。 UTF-8 没有。谢谢。
      【解决方案5】:

      其他答案为您提供了正确的方向。只是想添加 Guava 及其 Files.newReader(File,Charset) 辅助方法使得创建这样的 BufferedReader 非常易读(请原谅双关语):

      BufferedReader rEntrada = Files.newReader(new File(ficheroEntrada), Charsets.UTF_8);
      

      【讨论】:

        猜你喜欢
        • 2013-11-10
        • 2011-03-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-25
        • 2014-10-29
        相关资源
        最近更新 更多