Java的字符集/字符编码

时间:2012-11-21 14:56:16

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

我有一个西班牙语文件,所以它有很多字符,如:

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

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

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;

当我读取令牌列表时,所有特殊字符都消失了,并被这种字符替换:

Ó = Ó
Ñ = Ñ

等等......

发生了什么事?我从未遇到过charsets的问题(我假设是charset问题)。是因为这台电脑吗?我能做什么?

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

5 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分:4)

  

发生了什么事?

建议使用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-mode,这样我就可以在文件中看到确切的二进制数据。我确信有更好,更现代的方法来做到这一点。

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

答案 2 :(得分:2)

您的默认编码错误。您可能需要阅读UTF8或latin1。请参阅此代码段以在流上设置编码。另请参阅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();
        }

    }
}

答案 3 :(得分:2)

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

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

答案 4 :(得分:0)

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

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