2009-07-04

Apache Commons IO - Full of Simple IO Goodness

If you are writing Java applications that use IO (e.g. through file or socket operations), you should get familiar with the API of the Apache Commons IO library. It is not a complex framework which helps you adhere to coding best practices, nor is it an underlying implementation breakthrough that boost the performance of your applications. However, it will save you a lot of coding time, and it is very easy to make use of, as we shall see.

The library can be broken down to four main areas: filters, comparators, streams/readers/writers and utilities, and they are described in further details.

Filters (in Package org.apache.commons.io.filefilter)

Implementations of the java.io.FileFilter and the java.io.FilenameFilter interfaces.

These are useful if you are getting a list of files or filenames (e.g. contents of a directory), and you want to include only certain types of files. An example of this is the HiddenFileFilter class which contain singleton instances HiddenFileFilter.HIDDEN and HiddenFileFilter.VISIBLE which helps you to filter files by whether they are hidden or not, respectively.

In other words, if you want to get the names of the hidden files in a directory, you can do this:

File directory = new File("/some/directory");
String[] filenames = directory.list(HiddenFileFilter.HIDDEN);


Comparators (in Package org.apache.commons.io.comparator)

Implementations of the java.util.Comparator interface.

These may save you time writing your own implementations when you are looking to sort a list of files by their metadata. Examples of these are the ExtensionFileComparator (helps you to sort files by their file extensions) and the SizeFileComparator (helps you to sort files by their sizes).

So, if you want to sort a list of files by their size, you only need to do this:

List filesList = ... // Obtain a list of files from somewhere
Collections.sort(filesList, SizeFileComparator.SIZE_COMPARATOR);


Actually, with the SizeFileComparator, it doesn't end there. If you have a list of directories, and you want to sort them by the total size of their contents (recursively), you can use it like this:

List directoriesList = ... // Obtain a list of directories from somewhere
Collections.sort(directoriesList, SizeFileComparator.SIZE_SUMDIR_COMPARATOR);


Streams and Readers/Writers (in Packages org.apache.commons.io.input and org.apache.commons.io.output)

Implementations of the java.io.InputStream, java.io.OutputStream, java.io.Reader and java.io.Writer interfaces.

A useful one is the TeeInputStream (conversely TeeOutputStream). This is a decorator wrapper that adds a tee-like functionality to the underlying input stream. Its constructor takes in an input stream (the input stream it is supposed to wrap) and an output stream. When you call any of its overloaded read methods, the byte(s) that is read is also written to the output stream (which you passed in through the constructor).

Another interesting one is the CloseShieldInputStream. You may find it useful in such a scenario:

InputStream inputStream = ... // Obtain input stream from somewhere
someThirdPartyObject.processStream(inputStream); // Call a third-party method to do some processing

int b = inputStream.read(); // The third-party method is done but you need to do some further reads

// But OOPS! The method from the third-party library has actually already responsibly closed the input stream!


What you can do, is to wrap the inputStream with the CloseShieldInputStream, and pass the instance of the CloseShieldInputStream to the third-party method instead. When close() is called on the CloseShieldInputStream instance, the call does not propagate to the underlying inputStream object, leaving you free and safe to operate on it when the method returns.

Utilities (in Package org.apache.commons.io)

This is, in my opinion, the most useful area of the library, and any Java programmer must really get to know these utility classes. This is because, if you have done any IO programming in Java, you will find that some of the common few lines of code fragments which you have written and rewritten, can be replaced by a simple call to a method in one of these utility classes.

A few examples:

- Closing an input stream without throwing an exception:

Instead of writing

if (inputStream != null)
{
    try
    {
        inputStream.close();
    }
    catch (final IOException ignore)
    {
        //
    }
}


you can write

IOUtils.closeQuietly(inputStream);

- Copying a file:

Instead of getting the source file input stream, the target file output stream, reading/writing bytes from/to the input/output stream, and cleaning up (closing) the resources, you can write

FileUtils.copyFile(sourceFile, targetFile);

- Deleting a directory and all its content, recursively:

Instead of writing a recursive method and calling that method, you can write

FileUtils.deleteDirectory(directory);

In short, Apache Commons IO is a library that any Java developer should really get to know intimately, as it will really save a lot of unnecessary time re-inventing the wheel. HTH.

0 comments: