Alternative to File.exists() in Java
Asked Answered
N

6

10

I never thought it would happen to me, but I ran into my first bug in Java:

https://bugs.java.com/bugdatabase/view_bug?bug_id=5003595

I'm pretty much in the same exact situation as described in the bug (NFS on linux), and I'm seeing that File.exists() is not returning the correct value (at least not right away).

So my question is, is there any alternative to this method of checking if a file exists? I'd prefer to keep it OS agnostic if possible.

EDIT: I have found a workaround. If you make a call to ls $filedir, the NFS refreshes whatever cache/metadata that is giving Java trouble, and File.exists() returns the correct value. Granted, this isn't totally ideal, since it hurts portability, but there are ways to deal with that problem.

Noll answered 30/9, 2010 at 17:17 Comment(4)
What kind of file is it? Are you looking for a particular kind of file? Or just any file? You could run System.exec("ls") and parse the results for your file. Though I'm sure there are easier ways so I'll leave this as a commmentGrizzled
This bug is specific to Java 1.4.2_03, which reached the end of its support lifecycle years ago. Out of curiosity, why not just migrate to Java 5 or up? Have you tried testing with a supported JRE to see of anything breaks?Vicarial
@Steve: I am running Java 6. I'm assuming that since they marked 'will not fix' for this bug, that it isn't fixed in any version of Java. At least, thats what the behavior of my app tells me.Noll
Bizarre. I agree with Ben below, in that File.exists() can report false positives (i.e. saying a file exists when it doesn't). However, a false NEGATIVE is different (i.e. saying a file doesn't exist when it's sitting right there). That bug report is over 6 years old, and the comments indicate that they were addressing this in the development for JSR 203... so if you still see this in a contemporary JRE, I would file a new bug report. However, the two answers below are pretty much correct... the best workaround is simply try-catch blocks.Vicarial
H
7

The basic problem you have with NFS is that it caches attributes, files and directories information. This means the information can be out of date. You might be able to turn off caching, you will see a significant reduction in performance.

The important thing to remember is that NFS is not a messaging service and is not designed for timely delivery of data.

Hereinbefore answered 30/9, 2010 at 20:6 Comment(1)
This is about as close of an answer I can mark. The problem really lies more closely to the fact that an NFS is being used. In my situation, a file with filename x.file is made, then deleted, then re-made with the same name (x.file). After it is re-made, calls to stat on the file claim that it doesn't exist. Calling 'ls' on the whole directory seems to refresh the cache and fix Java's file.exists() problem, and calls to stat also start returning correctly. This seems to indicate the problem is more to do with NFS than Java.Noll
C
8

I experienced the same problem and solved it with a call to file.getParentFile().list(). Essentially the same as your solution, but OS agnostic.

Cerellia answered 3/8, 2015 at 8:51 Comment(1)
@SteveCohen It probably busts whatever cache is being looked at. In which case it implies a performance penalty as well.Urbanus
H
7

The basic problem you have with NFS is that it caches attributes, files and directories information. This means the information can be out of date. You might be able to turn off caching, you will see a significant reduction in performance.

The important thing to remember is that NFS is not a messaging service and is not designed for timely delivery of data.

Hereinbefore answered 30/9, 2010 at 20:6 Comment(1)
This is about as close of an answer I can mark. The problem really lies more closely to the fact that an NFS is being used. In my situation, a file with filename x.file is made, then deleted, then re-made with the same name (x.file). After it is re-made, calls to stat on the file claim that it doesn't exist. Calling 'ls' on the whole directory seems to refresh the cache and fix Java's file.exists() problem, and calls to stat also start returning correctly. This seems to indicate the problem is more to do with NFS than Java.Noll
E
6

What happens if File.exists() returns true, then someone deletes the file/your NFS mount goes away, then you try and open the file? Basically, File.exists() is useless since you need to handle the exceptions that can arise from opening the file anyway.

Engrave answered 30/9, 2010 at 17:24 Comment(0)
M
5

All File.exists tells you is whether the file existed at some point in the past. It doesn't tell you:

  • Whether it will exist when you try to open it
  • Whether you have permission to open it
  • Anything useful at all, really

So try to design your application so it can handle files that don't exist without trying to check for that in advance. (You'll have to handle various exceptions when actually working with the file.)

Matchbox answered 30/9, 2010 at 17:22 Comment(1)
You are assuming I'm going to open the file later, which isn't true in my particular situation. I don't actually end up opening the file in my application at all; I'm checking for existence for other reasons.Noll
S
4

I notice that Java 7's java.nio.file.Path.exists() method returns false if the file doesn't exist or it's existence can't be determined. It would seem, therefore, that false negatives will be around for a while and that your code will need to tolerate them.

Sarnoff answered 30/9, 2010 at 18:35 Comment(0)
R
2

The obvious alternative is File.isFile(). Try that first.

Although it will become inaccurate when reading read-only files you could always use the File.canWrite() to check if the file exists.

If both the above fail you could use the File.length(). If it returns 0L you know that the file does not exists.

Renzo answered 30/9, 2010 at 17:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.