当文件存在时,File.exists()返回false

101

我遇到了一个似乎没有任何逻辑的错误。我有一个文件对象,它是这样创建的:

File file = new File("utilities/data/someTextFile.txt");

然后我执行file.exists(),它返回false(!?)。如果文件未找到,我会将f.getAbsolutePath()记录到文件中。查看路径时,似乎一切正常。我可以将完整路径复制粘贴到Windows的“运行”窗口中,文件就能打开。

该文件始终存在,并且在应用程序运行期间未被删除或更改。它位于本地计算机上。

这种情况只在某些情况下发生。我可以随时重现故障,但我确定文件对象的路径不会因我重现故障而改变。

什么原因会导致file.exists()返回false?这与权限或文件锁有关吗?


是的,即使exists()返回false,我仍然可以从文件中读取。 - atsjoo
1
需要什么来重现故障? - user85421
1
这是在一个应用程序内部调用由Matlab编写并编译到Java应用程序中的函数。似乎是改变“当前目录”的Matlab函数导致了问题的出现。在创建文件对象时,我使用了绝对路径,因此这不应该是个问题 - 然而它似乎确实是个问题。当然,我已经验证了文件对象的绝对路径,并且它是正确的(与Matlab函数更改当前目录之前相同)。 - atsjoo
7
你是否在使用远程目录(例如NFS挂载)? - Tomer Gabel
这在Netbeans中很容易复现,只需创建一个单元测试来创建一个文件(例如写入zip文件),然后检查它是否存在。如果有人找到了明确的原因,那就太好了。 - Bloodboiler
显示剩余3条评论
18个回答

47

我在Windows 7上看到了以下情况:

file.exists() == false
file.getAbsoluteFile().exists() == true

涉及的文件是“var\log”,绝对路径确实指向一个存在于正常子目录(而非虚拟存储)中的文件。这可以从IDE中看到。
在文件上运行的操作会根据当前目录解析,而getAbsolutePath则会根据user.dir解析。如果这两个路径不匹配,则会得到冲突的结果。
请参见https://bugs.java.com/bugdatabase/view_bug?bug_id=4483097

18
显然,对文件执行的操作是针对当前目录解析的,而getAbsolutePath则是针对user.dir解析的。如果这两个路径不匹配,就会得到冲突的结果。魔鬼般的问题! - Roman Zenka
3
我有完全相同的问题,我尝试使用两种方法来检查文件是否存在,但仅在 Windows 7 上得到 false!有什么想法吗? - Dejell
1
对于任何正在开发动态 Web 项目的人来说,使用 file.exists() 会抛出一个异常,请使用 file.getAbsoluteFile().exists() 来检查 WEB-INF 目录中的文件(一般建议,不仅适用于 Windows 7)。 - P-S
2
@RomanZenka 链接已失效,正确的链接为https://bugs.java.com/bugdatabase/view_bug.do?bug_id=4483097 - kutschkem
1
更新的链接:https://bugs.java.com/bugdatabase/view_bug?bug_id=4483097 - wknauf
显示剩余2条评论

17

看起来在 Java 中指定路径的方式是有差异的。

例如,如果文件路径被指定为 file:/C:/DEV/test.txt,那么

File f = new File(filename);
f.exists();

将返回false。该路径可能在资源管理器或浏览器中有效,但它是一个URL而不是绝对文件路径。

另一方面,如果文件路径被指定为C:/DEV/test.txt,则

File f = new File(filename);
f.exists();

此方法将返回true,因为路径不是URL,而是绝对路径。

使用Spring Framework时,ResourceUtils.getFile(filename) 正好可以实现此功能——其中名称可以是URL或绝对文件路径。


6
我不认为 file:/C:/DEV/test.txt 可以作为路径名运行。它是一个URL而不是路径名。虽然一些人会犯这个错误,但没有证据表明原帖作者犯了这个错误... - Stephen C

16
如果该进程没有权限确定文件是否存在,它将返回false。可能可以打开文件,但不能通过正常方法确定文件是否存在。

21
有趣。你能展开一下吗?你具体考虑了哪些权限? - Clément
这里可能会出现java.nio.file.AccessDeniedException阻止访问文件/目录的情况。例如,如果您在FAR或其他文件资源管理器中打开了目录,然后删除了该目录及其所有嵌套文件,并检查该目录的存在性,则可能会为您保留临时文件而导致AccessDeniedException(扩展IOException)。在这种情况下,Files.exists将返回IOException的false。 - Alfira

12

上述答案对我的情况没有帮助。如上所述,我有:

file.exists() => false
file.getAbsoluteFile().exists => true

这个问题的根本原因在于 Windows 7 机器的所有者已经修改了CMD的注册表,以便它自动运行一个命令来启动到一个特定目录以使用Python。 这个修改瘫痪了Java1.6 代码,该代码显然在Windows上使用CMD进行某些文件操作(例如exists())。从注册表中删除自动运行即可解决此问题。


1
3.5年后,我遇到了同样的问题。我设置了一个自动运行脚本,每次启动cmd.com时配置环境变量。它甚至没有改变当前目录——只是一些doskey宏和一些环境变量。我删除了自动运行,并手动运行文件中的命令,突然File.exists()正确地工作了。 - Homr Zodyssey
2
哇,真的有效(两个都是),我只是愚蠢地检查了错误的文件,并偶然发现这个问题,以找出为什么它们都对我无效 :) 顺便说一句,在第二行的exists后面好像缺少了() ;) - RAM237

5
当勾选了“隐藏已知文件类型的扩展名”后,在[资源管理器]/[运行窗口]中输入“t.txt”时,Windows会打开“t.txt.txt”,但在程序中却不会。

2
我曾经遇到过这个问题,问题出在我在C:\test中创建了一个名为“testFile.txt”的txt文件。我使用路径C:\test\testFile.txt引用此文件,但无法正常工作。原因是该文件实际上被保存为testFile.txt.txt,因此以上解决方案得到了赞同(虽然这是一个旧问题,但没有被接受的答案!)。 - Theblacknight
上帝啊,Windows 真的太烂了。 - aafc

3
如果你不想每次调用方法时都要处理 getAbsoluteFile() 调用,最好创建一个带有绝对路径的文件实例。可以通过以下方式解决问题:
File file = new File("utilities/data/someTextFile.txt").getAbsoluteFile();

我建议将其放在try-catch块中。


3
显然,有许多可能的原因,之前的答案已经很好地记录了它们,但是这是我在一个特定情况下解决这个问题的方法:
我的一位学生遇到了这个问题,我几乎要把头发都拔光了才想出解决办法。事实证明,文件并不存在,尽管看起来像存在。问题在于 Windows 7 配置为“隐藏已知文件类型的文件扩展名”。这意味着如果文件看起来是“data.txt”,其实际文件名是“data.txt.txt”。
希望这能帮助其他人节省一些头发。

我认为这不是我的问题所在。正如我在问题中提到的:“我可以将完整路径复制粘贴到Windows的“运行”窗口中,文件就能正常打开。” 这意味着该文件确实存在。 - atsjoo

2
new File命令只是使用给定的路径名创建文件的实例,它并不会在硬盘上实际创建文件。
如果你想要在硬盘上创建文件,需要使用createNewFile()方法。
File file = new File ("path");
file.exists() 

只有当存在具有相同路径的现有文件时,此函数才会返回 true。如果您想检查是否与第一行中声明的相同文件,请使用以下方式。

File file = new File ("path");
file.createNewFile();
file.exists();

现在这将返回 true。

每次使用new关键字调用构造函数都会创建一个对象 - 就像在这种情况下由名称为File的类描述的对象一样!因此,不是File的实例!=描述符 :) - ceph3us

2
为了概括问题,问题出现在将URL/URI转换为本地路径时。最初的回答。
Example: URL url = file:/D:/code%20repo%20sample/sample.txt

// To remove url reference
String localPath = url.getPath();  
> /D:/code%20repo%20sample/sample.txt

// Decoding reserved characters in url from hexadecimal to character
URLDecoder.decode(localPath, StandardCharsets.UTF_8.toString()); 
> /D:/code repo sample/sample.txt

最初的回答。希望这能帮到你。

1
在我这种情况下,文件保存在。
filepath = Environment.getExternalStorageDirectory().getAbsolutePath()+ "/VRSI/Audio/"+encrypted_filename+".mp3";

它存储在 中。
/storage/emulated/0/VRSI/Audio/82B0999F16251F0DFE849F380D6AAEEA.mp3

当我获取文件路径时,它是这样的

/storage/emulated/0/Android/data/com.numerotec.vrsi/files/VRSI/Audio/AF7DC6C0C0B3EF3529EC70DAEF2324E0.mp3

所以我将字符串 "Android/data/com.numerotec.vrsi/files/" 替换为空。
之后。
if (file.getAbsoluteFile().exists())
{
    // write your code
} 

工作正常


抱歉,我不知道如何在StackOverflow上格式化代码。 - Ganesan J
感谢您对代码进行格式化。谢谢您,先生。 - Ganesan J
我有同样的问题,但是我绝对肯定这在IDE中是起作用的,但是在从我们的独立应用程序运行时不知何故却不能运行。 - Daniel
getAbsoluteFile() 可以工作,但现在我担心在期望相对路径工作的类似情况下会失败... - Daniel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接