Search code examples
javadosfile-attributes

Type guarantees for getting DOS file attributes in Java


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?


Solution

  • 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.