依赖于默认编码,我应该使用什么以及为什么?

Nik*_*las 23 java encoding findbugs internationalization

FindBugs报告了一个错误:

依赖于默认编码找到对将执行字节到String(或String to byte)转换的方法的调用,并假设默认平台编码是合适的.这将导致应用程序行为在平台之间变化.使用备用API并显式指定charset名称或Charset对象.

我像这样使用FileReader(只是一段代码):

public ArrayList<String> getValuesFromFile(File file){
    String line;
    StringTokenizer token;
    ArrayList<String> list = null;
    BufferedReader br = null;
    try {
        br = new BufferedReader(new FileReader(file));
        list = new ArrayList<String>();
        while ((line = br.readLine())!=null){
            token = new StringTokenizer(line);
            token.nextToken();
            list.add(token.nextToken());
    ...
Run Code Online (Sandbox Code Playgroud)

要纠正我需要改变的错误

br = new BufferedReader(new FileReader(file));
Run Code Online (Sandbox Code Playgroud)

br = new BufferedReader(new InputStreamReader(new FileInputStream(file), Charset.defaultCharset()));
Run Code Online (Sandbox Code Playgroud)

当我使用PrintWriter时,发生了同样的错误.所以现在我有一个问题.当我可以(应该)使用FileReader和PrintWriter时,如果不是很好的做法依赖于默认编码?第二个问题是正确使用Charset.defaultCharset()?我决定使用这种方法自动定义用户操作系统的字符集.

JB *_*zet 23

如果文件在您的应用程序的控制之下,并且您希望以平台的默认编码对文件进行编码,则可以使用默认的平台编码.明确地指定它会使您和未来的维护者更清楚,这是您的意图.例如,对于文本编辑器来说,这将是一个合理的默认设置,然后编写该平台上任何其他编辑器随后可以读取的文件.

另一方面,如果要确保可以在文件中写入任何可能的字符,则应使用UTF8之类的通用编码.

如果文件来自外部应用程序,或者应该与外部应用程序兼容,那么您应该使用此外部应用程序所期望的编码.

您必须意识到的是,如果您编写的文件就像您在计算机上所做的那样,并且在另一台没有相同默认编码的计算机上进行读取时,您将不一定能够读你写的东西.使用特定的编码,写入和读取,如UTF8,确保文件始终是相同的,无论在编写文件时使用什么平台.

  • 值得建议的是,即使使用默认编码,为了清楚起见,也明确指定*. (4认同)

McD*_*ell 22

理想情况下,它应该是:

try (InputStream in = new FileInputStream(file);
     Reader reader = new InputStreamReader(in, StandardCharsets.UTF_8);
     BufferedReader br = new BufferedReader(reader)) {
Run Code Online (Sandbox Code Playgroud)

...要么:

try (BufferedReader br = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
Run Code Online (Sandbox Code Playgroud)

...假设文件编码为UTF-8.

几乎所有非Unicode转换格式的编码都对于自然语言数据而言已经过时.没有Unicode,您无法支持某些语言.