【开发坑】new File(path).exists()和 Files.exists(Path) 返回结果不一致问题

本贴最后更新于 704 天前,其中的信息可能已经时异事殊

文件存在的情况下,如:D:/doc.txt
使用 new File("D:/doc.txt").exists() 返回的结果为 true,表示文件存在
使用 Files.exists(Path.of("D:/doc.txt")) 返回的结果为 false,文件不存在?

追溯原因:

Oracle Java Bug Databse 上发现了有人在 2004 年的 1.4.2 版本的 Java 就发现了相同的问题,他看了源码后发现是因为 File.exists 其实是用了 Linux 的 stat(2)命令,如果这个命令失败了,File.exists 就认为是文件不存在。

A DESCRIPTION OF THE PROBLEM : When operating on NFS-mounted volumes, java.io.File.exists will sometimes return “false” even though the file referenced actually does exist. The actual problem is a stale NFS file handle, which can occur for a number of reasons. An examination of the java source code shows that File.exists ends up performing a stat(2). If the stat fails, then File.exists assumes that the file being stat’ed does not exist. This is a false assumption. stat(2) can fail for several reasons other than ENOENT. One such “other” error is ESTALE, which is what I get if I use JNI to perform a “native” stat(2) on the same file that File.exists claims does not exist. STEPS TO FOLLOW TO REPRODUCE THE PROBLEM : I do not have a simple method for reproducing this problem, however an examination of the java sources will bear out my explantion above. EXPECTED VERSUS ACTUAL BEHAVIOR : EXPECTED - If the file exists, I expect java.io.File.exists to return “true” ACTUAL - java.io.File.exists returns “false” occasionally. REPRODUCIBILITY : This bug can be reproduced occasionally. (Incident Review ID: 191975)

然后解决方案是不解决。。。。

EVALUATION The error code should be examined from the stat. But exists does not throw IOException so what to do in such a case would have to be determined. ###@###.### 2004-03-24 Submitter is correct but this API is too limited to do anything useful when the stat returns a real error. We will try to address this issue in JSR203. ###@###.### 2004-03-25

所有只有换个实现方法了。检查文件是否存在时,可能会出现三种结果:

  • 该文件存在。
  • 该文件不存在。
  • 该文件的状态未知,因为该程序无权访问该文件。

有几种方法可以在 Java 中检查文件是否存在。如果文件存在,返回 true;文件不存在或文件的状态未知时,返回 false

一、使用 File.exists()方法

思路是使用该 File.exists()方法判断指定路径名表示的文件是否存在。如果文件存在,该方法返回 true;否则为 false

请注意,File.exists()当您的路径指向目录时返回 true。因此,建议将此方法与 File.isDirectory()检查目录的方法一起调用。如下所示:

import java.io.File; class Main { // Method to check if the file exists and is not a directory public static boolean isFileExists(File file) { return file.exists() && !file.isDirectory(); } public static void main(String[] args) { String filePath = "C:\\doc.txt"; File file = new File(filePath); if (isFileExists(file)) { System.out.println("File exists!!"); } else { System.out.println("File doesn't exist or program doesn't have access " + "to the file"); } } }

请注意,在 NFS 挂载的卷上操作时,java.io.File.exists 有时会返回 false ,即使引用的文件确实存在。请在此处查看错误详细信息。

二、使用 File.isFile() 方法

我们已经看到,File.exists() 如果您的路径指向一个目录,它会返回 true。要明确避免检查目录,建议使用 File.isFile() method 而不是 File.exists() method。该 File.isFile() 方法测试指定路径所指的文件是否为普通文件,即文件是否为目录。

import java.io.File; class Main { // Method to check if the file exists public static boolean isFileExists(File file) { return file.isFile(); } public static void main(String[] args) { String filePath = "C:\\doc.txt"; File file = new File(filePath); if (isFileExists(file)) { System.out.println("File exists!!"); } else { System.out.println("File doesn't exist or program doesn't have access " + "to the file"); } } }

三.使用 NIO Files.exists()

从 Java 7 开始,我们可以使用 java.nio.file.Files,它提供了几个对文件、目录或其他类型的文件进行操作的静态方法。要简单地检查文件是否存在,我们可以使用 exists()notExists() 的方法 java.nio.file.Files

exists() 如果文件存在,则该方法返回 true,而 notExists() 当文件不存在时,该方法返回 true。如果 exists()notExists() 都返回 false,则无法验证文件是否存在。当程序无权访问该文件时,可能会发生这种情况。

请注意,Files.exists() 当您的路径指向目录时返回 true。因此,建议将此方法与检查目录文件的方法 Files.isDirectory() 一起使用。如下所示:

import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; class Main { public static void main(String[] args) { String filePath = "C:\\doc.txt"; Path path = Paths.get(filePath); boolean exists = Files.exists(path); boolean notExists = Files.notExists(path); boolean isDir = Files.isDirectory(path); if (isDir) { System.out.println("File is a Directory"); } else if (exists) { System.out.println("File exists!!"); } else if (notExists) { System.out.println("File doesn't exist!!"); } else { System.out.println("Program doesn't have access to the file!!"); } } }

或者,我们可以使用以下方法检查路径是否为常规文件(而不是目录)Files.isRegularFile()

import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; class Main { public static void main(String[] args) { String filePath = "C:\\doc.txt"; Path path = Paths.get(filePath); boolean exists = Files.isRegularFile(path); if (exists) { System.out.println("File exists!!"); } else { System.out.println("File doesn't exist!!"); } } }

参考:
java.io.File.exists 在文件存在时返回 false 的 BUG
Check if a file exists in Java
Java Bug Database

  • 一些有用的避坑指南。

    69 引用 • 93 回帖
  • 教程
    144 引用 • 626 回帖 • 8 关注
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3194 引用 • 8214 回帖
1 操作
yexuejc 在 2023-04-21 16:58:41 更新了该帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...