views:

2174

answers:

3

I need to determine if a user-supplied String is a valid file path (i.e. if createNewFile() will succeed or throw an Exception) but i don't want to bloat the file system with useless files created just for validation purposes, so is there a way to determine if the String i have is a valid file path without attempting to create the file?

I know the definition of "valid file path" varies depending on the OS, but i was wondering if there was any quick way of accepting "C:/foo" or "/foo" and rejecting "banana"...a possible approach may be attempting to create the file and eventually deleting it if the creation succeeded, but i hope there is a more elegant way of achieving the same result...

+6  A: 

This would check for the existance of the directory as well.

File file = new File("c:\\cygwin\\cygwin.bat");
if (!file.isDirectory())
   file = file.getParentFile();
if (file.exists()){
    ...
}

It seems like file.canWrite() does not give you a clear indication if you have permissions to write to the directory.

krosenvold
Uhm...i don't want to check if the file exists, i want to check if the file can be created on the current file system
Raibaz
The problem there is that the ability to create the file could change after you've checked to see if it could be created
MrWiggles
krosenvold's code is doing the following: Does the filename passed in exist already as a directory, and if not, does the directory it would be in exist? This makes sense since if the directory is there you can create the file (permissions allowing) Note that new File("foo") doesn't create a file.
mtruesdell
+7  A: 

A number of things can go wrong when you try and create a file:

  • Your lack the requisite permissions;
  • There is not enough space on the device;
  • The device experiences an error;
  • Some policy of custom security prohibits you from creating a file of a particular type;
  • etc.

More to the point, those can change between when you try and query to see if you can and when you actually can. In a multithreaded environment this is one of the primary causes of race conditions and can be a real vulnerability of some programs.

Basically you just have to try and create it and see if it works. And that's the correct way to do it. It's why things like ConcurrentHashMap has a putIfAbsent() so the check and insert is an atomic operation and doesn't suffer from race conditions. Exactly the same principle is in play here.

If this is just part of some diagnostic or install process, just do it and see if it works. Again there's no guarantee that it'll work later however.

Basically your program has to be robust enough to die gracefully if it can't write a relevant file.

cletus
DON"T DIE (in some cases), allow the user to pick another volume or media. I have an IDE that dies when it can't write its project file. Well the volume is offline - allow me to select another spot and continue.
jim
+1  A: 

File.getCanonicalPath() is quite useful for this purpose. IO exceptions are thrown for certain types of invalid filenames (e.g. CON, PRN, *?* in Windows) when resolving against the OS or file system. However, this only serves as a preliminary check; you will still need to handle other failures when actually creating the file (e.g. insufficient permissions, lack of drive space, security restrictions).

Zach Scrivena