File Handling with Java NIO (New I/O)

Java NIO (New I/O) is a collection of APIs under the java.nio package that provide more scalable, flexible, and high-performance I/O operations. The primary benefit of NIO is its ability to handle file I/O in a non-blocking manner, as opposed to the traditional I/O APIs, which block the execution while reading or writing data.

  • Channels: Represent an open connection to a data source (file, socket, etc.).
  • Buffers: Containers for data that are read from or written to channels.
  • Selectors: Allow a single thread to handle multiple channels in a non-blocking manner.
  • Path and Files: Classes to manage file paths and perform operations like reading and writing.

Path Class and Working with File Paths

In Java NIO, the Path class is a crucial component for handling file paths. It’s part of the java.nio.file package and replaces the File class in traditional I/O. The Path class provides methods for manipulating file paths in a platform-independent manner, making our code more flexible across operating systems.

Creating a Path object

The Paths.get() method creates a Path object from a string or URI. We can use the Path object to perform various file operations like checking existence, reading, or writing.

Common Path Methods

  • path.getFileName(): Returns the file name.
  • path.getParent(): Returns the parent directory of the path.
  • path.toAbsolutePath(): Returns the absolute path of the file.

Reading and Writing Files with Files Class

The Files class, also part of java.nio.file, simplifies file operations like reading and writing. It provides various static methods to interact with files in a way that’s more efficient than the traditional I/O.

Reading a File

Writing to a File

BufferedWriter vs Files.write() in NIO

Both BufferedWriter and Files.write() can be used to write content to a file, but there are key differences in how they function.

  • BufferedWriter: This class is used when we need to write characters to a file with buffering. It is best suited for writing text data line by line. We can use it in combination with FileWriter for performance benefits in scenarios where writing to a file is done in multiple small chunks.

  • Files.write(): This method is more straightforward and is used for writing byte or character data to files. It’s useful for scenarios where we have the entire content ready to write.

BufferedWriter offers more control over buffering and writing large chunks of data efficiently. Files.write() is simpler and better suited for small, direct file writing tasks, such as writing entire collections.

Directory Traversal Using NIO

Java NIO provides the Files.walk() method for traversing directories in a recursive manner. This method returns a stream of paths, which allows for easy iteration over the directory contents.

Files.walk() is used to iterate through the directory and subdirectories, filtering out only regular files and printing their paths.

Working with FileChannel for High-Performance File Operations

The FileChannel class provides a more advanced and high-performance way to handle file I/O. It’s part of the NIO package and can perform non-blocking I/O operations, which is particularly useful when dealing with large files.

Reading Data Using FileChannel

In this example, FileChannel is used to read data in chunks using a ByteBuffer. This provides more control over the data and is ideal for large files or when we want to manipulate the file data in memory.

Writing Data Using FileChannel

FileChannel is particularly beneficial for tasks that require random access to file data, memory-mapped file access, and non-blocking I/O operations.