Is there a way in Java to determine if a path is valid without trying to create a file?

I need to determine if the user-supplied string is a valid file path (i.e. createNewFile() if createNewFile() succeeds or createNewFile() exception), but I do not want to split the file system with useless files created just for verification purposes.

Is there a way to determine if my string is a valid file path without trying to create the file?

I know that the definition of a "valid file path" varies by operating system, but I was wondering if there was any quick way to accept C: /foo or /foo and reject banana .

A possible approach would be to try to create a file and, ultimately, delete it if the creation was successful, but I hope there is a more elegant way to achieve the same result.

+56
java filesystems validation
Jan 22 '09 at 11:39
source share
7 answers

It also checks for a directory.

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

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

+27
Jan 22 '09 at 11:41
source share

The Path class introduced in Java 7 adds new alternatives, for example:
(Does not work properly under Linux - always returns true)

 /** * <pre> * Checks if a string is a valid path. * Null safe. * * Calling examples: * isValidPath("c:/test"); //returns true * isValidPath("c:/te:t"); //returns false * isValidPath("c:/te?t"); //returns false * isValidPath("c/te*t"); //returns false * isValidPath("good.txt"); //returns true * isValidPath("not|good.txt"); //returns false * isValidPath("not:good.txt"); //returns false * </pre> */ public static boolean isValidPath(String path) { try { Paths.get(path); } catch (InvalidPathException | NullPointerException ex) { return false; } return true; } 
+26
Feb 17 '16 at 9:31
source share

File.getCanonicalPath() quite useful for this purpose. IO exceptions for certain types of invalid file names (for example, CON , PRN , *?* On Windows) when resolving the OS or file system. However, this is only a preliminary check; you still have to handle other crashes when creating the file (for example, insufficient permissions, insufficient disk space, security restrictions).

+16
Jan 22 '09 at 13:25
source share

When trying to create a file, an error may occur:

  • You do not have the required permissions;
  • There is not enough space on the device;
  • The device is experiencing an error;
  • Some user security policies prevent you from creating a specific file type;
  • and etc.

Moreover, they can change between when you try to fulfill a request to find out if you can and when you can. In a multi-threaded environment, this is one of the main causes of race conditions and may be the real vulnerability of some programs.

Basically, you just need to try creating it and see if it works. And this is the right way to do it. This is why ConcurrentHashMap has putIfAbsent() , so checking and pasting is an atomic operation and does not suffer from race conditions. Exactly the same principle plays here.

If this is just part of the diagnostic or installation process, just do it and see if it works. Again, there is no guarantee that it will work later.

Basically, your program should be stable enough to die skillfully if it cannot write the corresponding file.

+15
Jan 22 '09 at 11:53
source share

Here you can do what works on different operating systems.

Use regex matching to check for existing known invalid characters.

 if (newName.matches(".*[/\n\r\t\0\f'?*\\<>|\":].*")) { System.out.println("Invalid!"); } else { System.out.println("Valid!"); } 

Pros

  • It works through operating systems.
  • You can customize it the way you want by editing this regular expression.

Cons

  • This may not be a complete list, and more research is needed to fill out more invalid patterns or characters.
0
Oct. 15 '18 at 18:59
source share

Just do it (and take it away)

A possible approach would be to try to create a file and, ultimately, delete it if the creation was successful, but I hope there is a more elegant way to achieve the same result.

Maybe this is the most reliable way.

The following is a canCreateOrIsWritable which determines whether your program can create a file and its parent directories at a given path or, if the file already exists there, write to it.

This is achieved by creating the necessary parent directories, as well as an empty file along the way. After that, he deletes them (if there was a file along the path, he remains alone).

Here is how you can use this:

 var myFile = new File("/home/me/maybe/write/here.log") if (canCreateOrIsWritable(myFile)) { // We're good. Create the file or append to it createParents(myFile); appendOrCreate(myFile, "new content"); } else { // Let pick another destination. Maybe the OS temporary directory: var tempDir = System.getProperty("java.io.tmpdir"); var alternative = Paths.get(tempDir, "second_choice.log"); appendOrCreate(alternative, "new content in temporary directory"); } 

The main method with several helper methods:

 static boolean canCreateOrIsWritable(File file) { boolean canCreateOrIsWritable; // The non-existent ancestor directories of the file. // The file parent directory is first List<File> parentDirsToCreate = getParentDirsToCreate(file); // Create the parent directories that don't exist, starting with the one // highest up in the file system hierarchy (closest to root, farthest // away from the file) reverse(parentDirsToCreate).forEach(File::mkdir); try { boolean wasCreated = file.createNewFile(); if (wasCreated) { canCreateOrIsWritable = true; // Remove the file and its parent dirs that didn't exist before file.delete(); parentDirsToCreate.forEach(File::delete); } else { // There was already a file at the path β†’ Let see if we can // write to it canCreateOrIsWritable = java.nio.file.Files.isWritable(file.toPath()); } } catch (IOException e) { // File creation failed canCreateOrIsWritable = false; } return canCreateOrIsWritable; } static List<File> getParentDirsToCreate(File file) { var parentsToCreate = new ArrayList<File>(); File parent = file.getParentFile(); while (parent != null && !parent.exists()) { parentsToCreate.add(parent); parent = parent.getParentFile(); } return parentsToCreate; } static <T> List<T> reverse(List<T> input) { var reversed = new ArrayList<T>(); for (int i = input.size() - 1; i >= 0; i--) { reversed.add(input.get(i)); } return reversed; } static void createParents(File file) { File parent = file.getParentFile(); if (parent != null) { parent.mkdirs(); } } 

Remember that between calling canCreateOrIsWritable and creating the actual file, the contents and permissions of your file system may have changed.

0
May 01 '19 at 15:30
source share
 boolean canWrite(File file) { if (file.exists()) { return file.canWrite(); } else { try { file.createNewFile(); file.delete(); return true; } catch (Exception e) { return false; } } } 
-one
Jul 14. '11 at 18:07
source share



All Articles