Performing I/O in Java

Java provides a number of different APIs for performing I/O, covering operations such as:

What can be slightly confusing about performing I/O in Java is that the relevant APIs have seen multiple overhauls over the language's 20 year history. This means that there can be several different ways of performing certain tasks such as reading data from files. These updates to the APIs also reflect changes and improvements in the I/O APIs provided by operating systems themselves, as well as trends in typical programming patterns (e.g. a move towards greater levels of concurrency).

With that in mind, Java provides the following broad set of I/O packages:

Package/APII/O facilities provided

Provides "classical" facilities, based on the model of stream-based I/O. This model has some advantages when it comes to flexibility and reusability: for example, we can write a method that reads data from any type of stream. To read data from a file, we can then pass that method a FileInputStream. But equally, we could pass it a ByteArrayInputStream to read cached data from memory.

While flexible, this model of I/O puts a lot of onus on the developer to handle lower-level issues such as buffering and error checking. It is a relatively verbose API: e.g. to read the contents of a file, we are forced to deal "manually" with the mechanics of creating a file input stream with relevant buffering, checking appropriately for error conditions and closing the file when finished.

The classical Java I/O API is not suitable for certain high-performance I/O as it requires all data to be copied from kernal space into user space.

This is the basic Java networking package and goes hand in hand with the package. The basic API is focussed on the one-thread-per-connection model of networking.

NIO (java.nio)

The new I/O or Java NIO package was introduced in Java 1.4. It provides additional facilities such as memory buffers, asynchronous I/O (including selectors to allow multiple connections to be handled by a single thread) and file mapping. It also provides limited kernel-kernel data transfers; with judicious use, this can provide greater efficiency for some operations.

NIO2 (java.nio.file)

The java.nio.file package (introduced in Java 7) is effectively a reworking of the original package. It provides various improvements with error handling, fills in gaps such has handling of symbolic links. NIO2 also provides less cumbersome API calls for performing simple I/O tasks such as reading and writing to files in Java. See the java.nio.file.Files class, which provides a number of simple static methods for reading/writing files, checking accessibility, copying and moving files etc.

If you enjoy this Java programming article, please share with friends and colleagues. Follow the author on Twitter for the latest news and rants.

Editorial page content written by Neil Coffey. Copyright © Javamex UK 2021. All rights reserved.