In a directory using Java I want to check each subdirectory for a DOS-specific attribute, but I want the code to run on other file systems as well. I can do this, which seems to be what the Java API implies is the recommended approach:
try {
DosFileAttributes attrs = Files.readAttributes(path, DosFileAttributes.class);
//TODO check DOS attrs
} catch(UnsupportedOperationException ex) {
//ignore the error; must be another file system
}
However that is ugly, against best practices (requires ignoring an exception), and probably less efficient because of the try/catch overhead. I'd prefer to do this (using Java 17 syntax to cast to DosFileAttributes
on the fly):
BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
if(attrs instance of DosFileAttributes dosFileAttributes) {
//TODO check DOS attrs
}
That's much cleaner. Much more understandable. Probably more efficient.
Unfortunately it's not clear to me if the API guarantees it to work (even though I see code all over the Internet assuming that the second approach will always work). In practice it would appear that OpenJDK will give me a DosFileAttributes
(actually a WindowsFileAttributes
) instance, even though I requested only a BasicFileAttributes
, because DosFileAttributes
implements BasicFileAttributes
and it's just as easy to always return the same object since it works in all situations.
But does the API guarantee that? From my reading, it would seem that, because I only requested a BasicFileAttributes
instance, some JDK implementation might (for various reasons, not just spite) decide to return only a BasicFileAttributes
instance (perhaps it doesn't want to go lookup the DOS attributes unless it was specifically asked).
So am I stuck with the ugly and inefficient exception-based approach if I want my code to be guaranteed to work?
There is no such guaranty written anywhere. This, however, does not imply that you are stuck with using exceptions. You can use, for example
DosFileAttributeView view = Files.getFileAttributeView(path,DosFileAttributeView.class);
if(view != null) {
DosFileAttributes attrs = view.readAttributes();
// proceed
}
At the first glance, you could pretest with Files.getFileStore(path) .supportsFileAttributeView( DosFileAttributeView.class)
, but the documentation of supportsFileAttributeView
says:
In the case of the default provider, this method cannot guarantee to give the correct result when the file store is not a local storage device. The reasons for this are implementation specific and therefore unspecified.
which is not very helpful. One thing you can do, is to test, whether the particular filesystem supports the DosFileAttributeView
in general. If path.getFileSystem() .supportedFileAttributeViews() .contains("dos")
returns false
, none of the paths of this filesystem will ever support this attribute.