My small utility application asks the user for an output directory via a GUI file selector.
Then it creates a lot of files in this output directory after some processing.
I need to check if the application has write access so that it informs the user and does
not continue with the processing (which might take a long time)
My first attempt was the canWrite() method of java.io.File. But this does not work
since it deals with the directory entry itself and not its contents. I have seen at least
one instance of a Windows XP folder that can be renamed or deleted but no files may be created
in it (because of permissions). This is actually my testcase.
I finally settled with the following solution
//User places the input file in a directory and selects it from the GUI
//All output files will be created in the directory that contains the input file
File fileBrowse = chooser.getSelectedFile(); //chooser is a JFileChooser
File sample = new File(fileBrowse.getParent(),"empty.txt");
try
{
/*
* Create and delete a dummy file in order to check file permissions. Maybe
* there is a safer way for this check.
*/
sample.createNewFile();
sample.delete();
}
catch(IOException e)
{
//Error message shown to user. Operation is aborted
}
However this does not feel elegant to me since it just tries to actually create a file and checks if the operation succeeds.
I suspect that there must be a better way for this but all solutions I have found so far
with Security Managers and stuff deal with Java Applets and not standalone applications.
Am I missing something?
What is the recommended way of checking for file access inside a directory before
actually writing the files?
I am using Java 5.
You could check the file permissions, make sure the directory exists, and do a lot of checking or find a library that does all that checking for you BUT (!) isn't the best way of checking to try ? If you check for permissions and the filesystem changes... you will have to change your code. But trying to write a file will ALWAYS tell you if you can write a file.
Your solution doesn't have to be the most elegant one. It's not a cheap hard coded patch or something ugly. It's just normal code. And it will always work. But if you don't like to see that check in the code just separate it by putting it in class which only goal is to check for the possibly of writing. In fact, you should put it in a utility class wheter you like the elegance or not.
The other solution would be to place your whole writing-to-the-hard-drive code, in the try. And if you can't write, the whole part will be skipped and you give feedback to the user with a message in the catch part.
it doesn't works even if you invoke canWrite
on the final path?
File sample = new File(fileBrowse.getParent(),"empty.txt");
if (sample.canWrite()) {
doSomethingUseful(sample);
} else {
notifyUser();
}
I'd say concentrate on providing a good user experience if/when the file can't be written, and just don't bother pre-checking the path. Since you say that the processing takes a ling tome, there's no way to guarantee that you'll still be able to write to that path when it finishes. The permissions could very well change between when you check and when you write, or the disk could fill up, or...
you can use FilePermission to get the details .
I find one way where you need to implement SecurityManager the code is here and here
Using Java 1.8 I was able to use the following.
Set<PosixFilePermission> permissions = Files.getPosixFilePermissions(Paths.get(destDir), LinkOption.NOFOLLOW_LINKS);
Assert.assertTrue("User did not have read permission.", permissions.contains(PosixFilePermission.OWNER_READ));
Assert.assertTrue("User did not have execute permission.", permissions.contains(PosixFilePermission.OWNER_EXECUTE));
Assert.assertTrue("User did not have write permission.", permissions.contains(PosixFilePermission.OWNER_WRITE));
Assert.assertFalse("Group did have read permission.", permissions.contains(PosixFilePermission.GROUP_READ));
Assert.assertFalse("Group did have execute permission.", permissions.contains(PosixFilePermission.GROUP_EXECUTE));
Assert.assertFalse("Group did have write permission.", permissions.contains(PosixFilePermission.GROUP_WRITE));
Assert.assertFalse("Others did have read permission.", permissions.contains(PosixFilePermission.OTHERS_READ));
Assert.assertFalse("Others did have execute permission.", permissions.contains(PosixFilePermission.OTHERS_EXECUTE));
Assert.assertFalse("Others did have write permission.", permissions.contains(PosixFilePermission.OTHERS_WRITE));