- Introduction to Java NIO with Examples
- Java Nio Write File Example
- Thank you!
- 1. Introduction to the NIO API
- 2. Creating a NIO Path
- 3. Writing files with the NIO API
- 3.1 Using NIO API with write()
- 3.2 Using NIO API with newBufferedWriter()
- 3.3 Using NIO API to copy a file with an Outputstream
- 4. Summary
- 5. Download The Source Code
Introduction to Java NIO with Examples
Java IO(Input/Output) is used to perform read and write operations. The java.io package contains all the classes required for input and output operation. Whereas, Java NIO (New IO) was introduced from JDK 4 to implement high-speed IO operations. It is an alternative to the standard IO API’s.
In this article, we will understand more about Java NIO.
Java NIO(New Input/Output) is high-performance networking and file handling API and structure which works as an alternative IO API for Java. It is introduced from JDK 4. Java NIO works as the second I/O system after standard Java IO with some added advanced features. It provides a different way of working with I/O than the standard IO. Like Java.io package which contains all the classes required for Java input and output operations, the java.nio package defines the buffer classes which are used throughout NIO APIs. We use Java NIO for the following two main reasons:
- Non-blocking IO operation: Java NIO performs non-blocking IO operations. This means that it reads the data whichever is ready. For instance, a thread can ask a channel to read the data from a buffer and the thread can go for other work during that period and continue again from the previous point where it has left. In the meantime, the reading operation is complete which increases the overall efficiency.
- Buffer oriented approach: Java NIO’s buffer oriented approach allows us to move forth and back in the buffer as we need. The data is read into a buffer and cached there. Whenever the data is required, it is further processed from the buffer.
The main working of the Java NIO package is based on some core components. They are:
- Buffers: Buffers are available in this package for the primitive data types. Java NIO is a buffer oriented package. It means that the data can be written/read to/from a buffer which further processed using a channel. Here, the buffers act as a container for the data as it holds the primitive data types and provides an overview of the other NIO packages. These buffers can be filled, drained, flipped, rewind, etc.
- Channels: Channels are the new primitive I/O abstraction. A channel is a bit like stream used for communicating with the outside world. From the channel, we can read the data into a buffer or write from a buffer. Java NIO performs the non-blocking IO operations and the channels are available for these IO operations. The connection to different entities is represented by various channels which are capable of performing non-blocking I/O operation. The channels work as a medium or a gateway. The following image illustrates the channel and buffer interaction:
- Selectors: Selectors are available for non-blocking I/O operations. A selector is an object which monitors multiple channels for the events. As Java NIO performs the non-blocking IO operations, selectors and the selection keys with selectable channels defines the multiplexed IO operations. So, in simple words, we can say that the selectors are used to select the channels which are ready for the I/O operation. The following image illustrates the selector handling the channels:
Java NIO provides a new I/O model based on channels, buffers and selectors. So, these modules are considered as the core of the API. The following table illustrates the list of Java.nio packages for an NIO system and why they are used:
Package | Purpose |
---|---|
java.nio package | It provides the overview of the other NIO packages.Different types of buffers are encapsulated by this NIO system, which are used throughout the NIO API’s. |
java.nio.channels package | It supports channels and selectors, which represent connections to entities which are essentially open the I/O connections and selects the channel ready for I/O. |
java.nio.channels.spi package | It supports the service provider classes for java.io.channel package. |
java.nio.file package | It provides the support for files. |
java.nio.file.spi package | It supports the service provider classes for java.io.file package. |
java.nio.file.attribute package | It provides the support for file attributes. |
java.nio.charset package | It defines character sets and providing encoding and decoding operations for new algorithms. |
java.nio.charset.spi package | It supports the service provider classes for java.nio.charset package. |
Why Java.nio.File, when Java.io.File is already present? It is a very common question that why we will move to Java.nio.File when Java.io.File is already present. There were a few things which were missing in the old Java.io.File and that led to the usage of the new Java.nio.File. The following are some of the things which were missing in the old package and the reasons why the new package is used:
- The old module provides limited support for the symbolic links.
- The old module provides limited support for file attributes and performance issues.
- The old module does not work consistently across all the platforms.
- The old module is missing with the basic operations like file copy, move, etc.
Java Nio Write File Example
With this example we are going to demonstrate how to use the Non-blocking I/O API, or NIO.2 API (NIO API) for short, to write data to a file. The examples in this article are compiled and run in a Mac OS unix environment. Please note that Java SE 8 is required to run the code in this article.
In order to help you master Java NIO Library, we have compiled a kick-ass guide with all the major Java NIO features and use cases! Besides studying them online you may download the eBook in PDF format!
Thank you!
1. Introduction to the NIO API
The NIO.2 API was introduced in Java 7 as a replacement for the java.io.File class. It provides a flexible, and intuitive API for use with files.
2. Creating a NIO Path
In order to write a file to the file system we must first create a Path for the destination of the file. A Path object is a hierarchical representation of the path on a system to the file or directory. The java.nio.file.Path interface is the primary entry point for working with the NIO 2 API.
The easiest way to create a Path Object is to use the java.nio.files.Paths factory class. The class has a static get() method which can be used to obtain a reference to a file or directory. The method accepts either a string, or a sequence of strings(which it will join to form a path) as parameters. A java.nio.file.Path , like a File , may refer to either an absolute or relative path within the file system. This is displayed in the following examples:
- p1 creates a relative reference to a file in the current working directory.
- p2 creates a reference to an absolute directory in a Unix based system.
- p3 creates a reference to the absolute directory /animals/dogs/labradors
3. Writing files with the NIO API
Once we have a Path Object we are able to execute most of the operations that were previously possible with java.io.File .
3.1 Using NIO API with write()
The Files.write() method is an option when writing strings to file. It is cleanly and concisely expressed. It is not a good idea to use a method like this to write larger files, due to its reliance on byte arrays. As shown below there are more efficient ways of handling these.
Path path = Paths.get("src/main/resources/question.txt"); String question = "To be or not to be?"; Files.write(path, question.getBytes());
3.2 Using NIO API with newBufferedWriter()
The NIO.2 API has methods for writing files using java.io streams. The Files.newBufferedWriter(Path,Charset) writes to the file at the specified Path location, using the user defined Charset for character encoding. This BufferedWriter method is preferential due to its efficient performance especially when completing a large amount of write operations. Buffered operations have this effect as they aren’t required to call the operating system’s write method for every single byte, reducing on costly I/O operations. Here’s an example:
Path path = Paths.get(«src/main/resources/shakespeare.txt»); try(BufferedWriter writer = Files.newBufferedWriter(path, Charset.forName(«UTF-8»)))< writer.write("To be, or not to be. That is the question."); >catch(IOException ex)
This method will create a new file at the given path, or overwrite it if it already exists.
3.3 Using NIO API to copy a file with an Outputstream
In this example we use the NIO API in conjunction with an output stream to copy a file and its contents from one file to a new instance with a new name. We achieve this by using the Files.copy() method, which accepts (Path source, Outputstream os) as its parameters.
Path oldFile = Paths.get(«src/main/resources/», «oldFile.txt»); Path newFile = Paths.get(«src/main/resources/», «newFile.txt»); try (OutputStream os = new FileOutputStream(newFile.toFile())) < Files.copy(oldFile, os); >catch (IOException ex)
The code above is an example of the try with resources syntax which was introduced in Java 7 and made it easier handle exceptions while correctly closing streams and other resources which are used in a try-catch block. FileOutputStream is used to handle binary data.
4. Summary
In this article we’ve introduced you a couple ways to use the NIO API to write a file to your file system. Along the way we’ve touched upon the Path object.
5. Download The Source Code
This was an example of writing to a file with Java NIO2 API.