File operation is quite platform dependent. Although Java is a cross platform programming language, the file operation in Java is also platform dependent. The obvious evidence is the file permission check. In Java, we can call canRead(), canWrite() and canExecutable() to check whether the program can read, write or execute the file specified. However, on Windows, when we call canRead() on a File object, we may get unexpected result.
Actually, on Windows, when we call canRead() on a File object, we will always get the true returned even if we have denied the read access to the file. There is also a bug for this and it's still not fixed. The bug details can be found here. We can use below codes to test this:
import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; public class FilePermissionTest{ public static void main(String args[]){ try{ File file=new File("test.txt"); System.out.println("Can read : "+file.canRead()); FileInputStream input=new FileInputStream(file); }catch(FileNotFoundException ex){ ex.printStackTrace(); } } }
The output will be:
Can read : true java.io.FileNotFoundException: test.txt (Access is denied) at java.io.FileInputStream.open(Native Method) at java.io.FileInputStream.(FileInputStream.java:106) at FilePermissionTest.main(FilePermissionTest.java:11)
From the output, we can easily find that the canRead() returns true while when we create the FileInputStream object, we get Access is denied error.
Is there any way to work around this issue on Windows? Yes, start from Java 7, we have the java.nio.file package and the java.nio.file.Files class, this should be used if you want to have more control over the file you want to operate on.
Now we have the code:
import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.nio.file.Files; import java.nio.file.FileSystems; public class FilePermissionTest{ public static void main(String args[]){ try{ File file=new File("test.txt"); System.out.println("Can read : "+file.canRead()); System.out.println("Is readable : "+Files.isReadable(FileSystems.getDefault().getPath(file.getAbsolutePath()))); FileInputStream input=new FileInputStream(file); }catch(FileNotFoundException ex){ ex.printStackTrace(); } } }
The output is:
Can read : true Is readable : false java.io.FileNotFoundException: test.txt (Access is denied) at java.io.FileInputStream.open(Native Method) at java.io.FileInputStream.(FileInputStream.java:146) at FilePermissionTest.main(FilePermissionTest.java:15)
From the output we can see the Files.isReadable() returns the correct value.
By the way, if you call setReadable() on a File object, you may also be disappointed.