繁体   English   中英

Java的字符集/字符编码

[英]Java's charsets / character encoding

我有一个西班牙文件,所以它充满了以下字符:

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

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

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问题)。 是因为这台电脑吗? 我能做什么?

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

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

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

发生了什么?

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

首先是http://www.utf8-chartable.de上的UTF-8字符表。 页面上有一个下拉菜单,可让您浏览Unicode的不同部分。 你的一个问题是Ó 检查图表显示,如果你的文件是用UTF-8编码的,那么字符是U+00D3 LATIN CAPITAL LETTER O WITH ACUTE ,UTF-8序列是两个字节,hex 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,这样我就可以在文件中看到确切的二进制数据。 我相信有更好,更现代的方法来做到这一点。

最后的想法 - 可能值得阅读绝对最低每个软件开发人员,绝对必须知道Unicode和字符集(没有借口!

您的默认编码错误。 您可能需要阅读UTF8或latin1。 请参阅此代码段以在流上设置编码。 另请参见Java,默认编码

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();
        }

    }
}

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM