Friday, August 27th, 2010

Low Level File Information For Java

This post is good news for some Java programmers. Once in a while you wish you knew a bit more about the files you access from Java. The class offers only a bare minimum of visibility.

If you are wrestling with this problem, and if you are on a Linux/Unix platform, download the filestat package from this website and get going. This post introduces the package briefly.

My interest was spawned by an excellent post: How to deal with filesystem softlinks/symbolic links in Java. It contains complete code for a native Java method to determine if a file is a symbolic link.

It was a long time since I did any JNI, so I felt inspired to dig into the more general problem of returning all of the C struct stat data to the Java level. The resulting FileStat Java class lets you access every bit of it.

If you wonder about the name, ‘stat(2)’ is the system call used in Linux/Unix to get information about a file. There is also a similarly named command ‘stat(1)’ that you may enter on the command line. It produces text output for human consumption.

On this level it is important to know about hard and soft (or symbolic) links. In a Linux/Unix file system any file is identified by its inode number. A file name is a hard link to an inode. Any number of names may be linked to the same inode. For instance, every directory contains entries named “.” and “..”. These are not shell conventions, but real file names, i.e. hard links. You may say that a Linux/Unix file system is a bag of inodes. Its structure is only determined by storage considerations. The directory tree structure we think is so essential is introduced by the file names linked to the inodes.

A symbolic link is a pointer to another file or directory. More exactly, it is a file containing the name of another file. It has a low level flag to indicate that this is a symbolic link. The flag may be accessed from Java through the filestat package.

Directories work in a similar way. A directory is just a file with a low level flag that indicates that its contents should be interpreted as a directory.

Another low level flag may indicate that a file is a socket. This kind of socket is a Unix domain socket, a device for interprocess communication. It is similar to network sockets, but works only for local processes. A Unix domain socket appears as a file in the file system, so it is natural that it can only be accessed locally. Unix domain sockets are heavily used by the KDE and Gnome desktop environments, for example.

In Linux/Unix devices appear as files, usually under /dev. This is a powerful metaphor. Want some high quality random numbers? It’s as easy as typing cat /dev/random. This example is contrived, but it shows the power of the concept. No special programming is necessary. Another example is /dev/null, the bottomless pit (or empty input). It may be used from the command line as well as programmatically.

The filestat package lets you check all those low level flags from Java. It also lets you access two file timestamps in addition to the last modification time present in The timestamps contain the time of last access (atime) and the time of the last status change (ctime). A status change is when you change the owner or the protection of a file, for instance. All timestamps are available with nanosecond precision, for what it’s worth.

The filestat package also contains a class named TestFileStat. You may use it from the command line. Give it one or more file paths. For each path it first prints the result of invoking FileStat methods. Then it runs the stat(1) command and prints its output for comparison.

The only caveat is that the filestat package comes to you as source code. It contains native methods, so you must compile the package on your own box. You need make and gcc (or some other C compiler).

Edit: See also this post

2 Comments on “Low Level File Information For Java”

  1. Johan Kaving

    Excellent information, that might very well turn out to be useful sometime.

    Note that there is an error in the link to the inspiring blog post. It should be


  2. Håkan

    Link error corrected. /Håkan