Java FileReader编码问题

nyb*_*bon 124 java unicode encoding file

我试图使用java.io.FileReader读取一些文本文件并将它们转换为字符串,但我发现结果编码错误,根本不可读.

这是我的环境:

  • Windows 2003,操作系统编码:CP1252

  • Java 5.0

我的文件是UTF-8编码或CP1252编码,其中一些(UTF-8编码文件)可能包含中文(非拉丁文)字符.

我使用以下代码来完成我的工作:

   private static String readFileAsString(String filePath)
    throws java.io.IOException{
        StringBuffer fileData = new StringBuffer(1000);
        FileReader reader = new FileReader(filePath);
        //System.out.println(reader.getEncoding());
        BufferedReader reader = new BufferedReader(reader);
        char[] buf = new char[1024];
        int numRead=0;
        while((numRead=reader.read(buf)) != -1){
            String readData = String.valueOf(buf, 0, numRead);
            fileData.append(readData);
            buf = new char[1024];
        }
        reader.close();
        return fileData.toString();
    }
Run Code Online (Sandbox Code Playgroud)

上面的代码不起作用.我发现即使文本是UTF-8编码,FileReader的编码也是CP1252.但是java.io.FileReader的JavaDoc说:

此类的构造函数假定默认字符编码和默认字节缓冲区大小是适当的.

这是否意味着如果我使用FileReader,我不需要自己设置字符编码?但我目前确实得到了错误的编码数据,处理我的问题的正确方法是什么?谢谢.

Joa*_*uer 235

是的,您需要指定要读取的文件的编码.

是的,这意味着您必须知道要读取的文件的编码.

不,没有通用的方法来猜测任何给定"纯文本"文件的编码.

FileReader始终使用平台默认编码的构造函数通常是一个坏主意.

而不是FileReader,你需要使用.new InputStreamReader(new FileInputStream(pathToFile), <encoding>)

  • @NobleUplift:最安全的赌注是`StandardCharsets.UTF_8`,没有打错有机会;-)但是,是的,如果你去用绳子`"UTF8"'会是正确的(虽然我似乎记得,这将接受左右逢源). (6认同)
  • 对于使用InputStreamReader的建议+1,但是在代码块中使用链接会使代码难以复制和粘贴,如果可以更改,则thx (3认同)

Mic*_*rdt 78

FileReader 使用Java的平台默认编码,这取决于它运行的计算机的系统设置,并且通常是该区域设置中用户中最常用的编码.

如果这个"最佳猜测"不正确,那么你必须明确指定编码.不幸的是,FileReader不允许这样(API中的主要疏忽).相反,您必须使用new InputStreamReader(new FileInputStream(filePath), encoding)并理想地从文件的元数据中获取编码.

  • "API中的主要疏忽" - 感谢您的解释 - 我想知道为什么我找不到我追求的构造函数!干杯约翰 (22认同)
  • 我甚至会说,如果你的Java应用程序在每次读取或写入文件/流/资源时都没有*明确地指定编码,那么它就会被破坏*,因为它*不能*可靠地工作. (5认同)

And*_*ver 11

对于 Java 7+文档,您可以使用:

BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8);
Run Code Online (Sandbox Code Playgroud)

这是所有字符集文档

例如,如果您的文件在 CP1252 中,请使用此方法

Charset.forName("windows-1252");
Run Code Online (Sandbox Code Playgroud)

这是 IO 和 NIO文档的Java 编码的其他规范名称

如果你不知道你在文件中得到的确切编码,你可以使用一些第三方库,比如来自谷歌的这个工具,它工作得相当整洁。


Rad*_*nov 6

从Java 11开始,您可以使用:

public FileReader(String fileName, Charset charset) throws IOException;
Run Code Online (Sandbox Code Playgroud)