Kotlin Files.readAttributes()

The Files.readAttributes() method comes from JDK and is used to return meta-data about a particular file.

import java.nio.file.Files
import java.nio.file.Paths
import java.nio.file.attribute.BasicFileAttributes

fun main(args : Array<String>){
    val path =
            if(args.isEmpty()){
                Paths.get(System.getProperty("user.dir"))
            } else {
                Paths.get(args[0])
            }

    if(Files.isDirectory(path)){

        Files.list(path).forEach({ it ->
            val attrs = Files.readAttributes(it, BasicFileAttributes::class.java)

            println("${it.fileName}")
            println("Size => ${attrs.size()}")
            println("Directory => ${attrs.isDirectory}")
            println("Regular File => ${attrs.isRegularFile}")
            println("Link => ${attrs.isSymbolicLink}")
            println("Last Accessed => ${attrs.lastAccessTime()}")
            println("Last Modified => ${attrs.lastModifiedTime()}")
            println()
        })
    } else {
        println("Enter a path to a directory")
    }
}

The readAttributes() call is made on line 16. The readAttributes() method takes a Path object and then a Java class object of BasicFileAttribures or one of its subinterfaces, DosFileAttributes or PosixFileAttributes. Depending on the Java class specified, the method will return either BasicFileAttributes, DosFileAttributes, or PosixFileAttributes. BasicFileAttributes is used in this example because it is portable across all systems, while the other two interfaces are specific to their respective platforms.

BasicFileAttributes provides many commonly used file attributes in a type safe fashion. We can access common attributes such as when the file was created, modified, or last accessed. The interface has boolean attributes to check if a Path is a directory or symbolic links. We can even check the size of the file with the BasicFileAttributes.

The DosFileAttributes interface has properties specific to DOS based platforms (i.e., Windows). We can check if a file is a system file, hidden file, read only, or archived. The PosixFileAttributes interface is used on unix based platforms such as Mac OS X or Linux. It contains properties file permissions, user groups, and the file owner.

References

https://docs.oracle.com/javase/7/docs/api/java/nio/file/attribute/BasicFileAttributes.html
https://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html#readAttributes(java.nio.file.Path,%20java.lang.Class,%20java.nio.file.LinkOption…)

Advertisements

Koltin Files.getAttribute()

The Files class in JDK has a getAttribute() that accepts a Path object and returns a specified attribute.

import java.nio.file.Files
import java.nio.file.Paths

fun main(args: Array<String>) {
    val path =
            if (args.isEmpty()) {
                Paths.get(System.getProperty("user.dir"))
            } else {
                Paths.get(args[0])
            }
    if(Files.isDirectory(path)){

        Files.list(path).forEach({ it ->
            //getAttribute() asserts non-null, so we can add compiler null checks by declaring a nullable type if desired
            val creationTime = Files.getAttribute(it, "creationTime")
            val lastModified = Files.getAttribute(it, "lastModifiedTime")
            val size = Files.getAttribute(it, "size")
            val dir = Files.getAttribute(it, "isDirectory")

            println("${it.fileName}")
            println("Creation Time => $creationTime")
            println("Last Modified => $lastModified")
            println("Size => $size")
            println("Directory => $dir")
            println()
        })
    } else {
        println("Please enter a path to a directory")
    }
}

The demonstration of Files.getAttribute() is found on lines 15 – 18. In each case, the getAttribute() method accepts a Path object, a string name of the attribute, and optional LinkOptions. The value returned is of type any, and the return type is assert not null (!!) operator. Since the names of the attributes is a string, there is the possibility that an exception could get thrown also.

The getAttribute() method can be convient, but it has short comings. Since it is a Java class, Kotlin interprets it as returning assert non-null. This may or may not be a problem. The java-doc makes no mention of a null return type, so it’s most likely safe to assume non-null types. However, it compiler checks are wanted or desirable, then we can declare nullable types.

More troubling is the fact that Strings are used for the attribute types. We have no protections against a typo such as “sizes” when we meant “size”. We will get a runtime exception in the event that attribute doesn’t exist. Alway check the java document prior to using the getAttribute() method to make sure the attribute is available first, keeping in mind that some attributes are platform specific.

Note that there is also a readAttributes() method, found in an upcoming post, that offers much better type safety than getAttribute(). However, the getAttribute() is useful in the case that we wish to check only on specific attribute (such as size), without having to use additional objects.

References

https://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html#getAttribute(java.nio.file.Path,%20java.lang.String,%20java.nio.file.LinkOption…)