Java File.listFiles()根据`exists()`返回“不存在”的文件

时间:2016-10-14 17:22:06

标签: java file encoding

我在生产代码中注意到了这个问题:

java.lang.IllegalArgumentException: /somePath/�.png does not exist
    at org.apache.commons.io.FileUtils.sizeOf(FileUtils.java:2413)
    at org.apache.commons.io.FileUtils.sizeOfDirectory(FileUtils.java:2479)

根本原因是:

import java.io.File;

public class FileNameTest
{

    public static void main(String[] args)
    {
        File[] files = new File("/somePath").listFiles();
        for (File file : files)
        {
            System.out.println(file + " - " + (file.exists() ? "exists" : "missing!!"));
        }
    }

}

输出:

0.png - exists
7.png - exists
4.png - exists
8.png - exists
1.png - exists
3.png - exists
�.png - missing!!
2.png - exists
5.png - exists
�.png - missing!!
6.png - exists
d.png - exists
$.png - exists
s.png - exists
+.png - exists
9.png - exists

“缺失”文件以符号"µ" (Mu)"€" (Euro)命名。

似乎这些文件名使用了错误的编码。 当我在bash中列出文件时,它们也显示错误。 当我将ls的输出从latin1转换为UTF-8时,它们正确显示(至少为mu)。

但不过......

  1. 这些文件存在
  2. file.listFiles()列出了它们
  3. 对于2个特殊情况:file.exists()返回false
  4. 我相信这是JVM中的一个错误。任何人都可以证实这一点吗?

    是否已有错误报告?任何想法如何解决这一问题? (重命名文件不是一个选项,因为它们是用户生成的,可能会以任何形式或形状重新出现。)

    我的系统:

    • Ubuntu 4.2.0
    • java版“1.8.0_102”
    • Java(TM)SE运行时环境(版本1.8.0_102-b14)
    • Java HotSpot(TM)64位服务器VM(版本25.102-b14,混合模式)
    • Apache Commons IO 2.4

1 个答案:

答案 0 :(得分:3)

这不是错误,它是文件系统中缺少编码信息的结果。 Java无法正确表示文件名,因为它不知道编码。因此,如果没有指定正确的编码,则无法从Java访问该文件。

解决此问题的最简单方法是正确设置 file.encoding 属性,并在所有文件名中使用该编码。

编辑:我发现了一篇文章,显示了另一种可能的行为,可能更改了 file.encoding 也无济于事。如果你想使用UTF-8以外的东西,最好测试一下。 http://jonisalonen.com/2012/java-and-file-names-with-invalid-characters/

我还发现了一个相关的讨论:Setting file name encoding