Java 8 - Part VI [File I/O NIO.2]
In old versions, you could use the java.io.File to handle files. But there were problems with symbolic link, attributes, performance. The Java 1.4 introduced the NIO API, but it was not enough to solve the problems. The version 7 brings the NIO.2 API such a solution to help in the support to manipulate files and directories. Instead to use java.io.File, now you can use java.nio.file package (Path, Paths, and Files).
It is the sixth post of the Java 8 series about the changes that you can find from version 6 to 8 and it will introduce an overview about the NIO.2 API.
Summary
Manipulating files and directories
Java NIO.2 API is a replacement for the java.io.File class. This API will make our work with files easier.
- java.nio.file.Path interface: "A Path object represents a hierarchical path on the storage system to a file or directory. Path is a direct replacement for the legacy java.io.File class"
- java.nio.file.Paths: It is a factory class to create instance of Path, which is a location within the file system, and not the actual file.
- Helper class: It also has static methods but it differs in Paths because helper classes are focused on manipulating or creating new objects from existing instances, whereas factory classes are focused primarily on object creation. Many of the same operations available in java.io.File are available to java.nio.file.Path via a helper class called java.nio.file.Files.
File Attributes
File attributes are related to the metadata (not the contents of the file), such be hidden or about permission. You can reading common attributes using some Files methods such isDerectory, isRegularFile, isSymbolicLink. isHidden, isReadable, isExecutable, size. Also it's possible managing the modifications (getLastModifiedTime, setLastModifiedTime) and ownership (getOwner, setOwner.).
However, there are costs to access the file and get the metada, and some attributes are file system specific. The NIO.2 API allow you to construct views for several systems in one call. The view is a group of attributes related to a file system. If you need access many attributes, the use of view can help the performance.
All attributes classes extend from BasicFileAttributes, so you can use the common methods.
Walking by the structured path
To find a file or directory, you should walk by the path that is structured as a tree. So, you will start with the parent directory and iterate over its descendants.
The strategies to walk in the directory tree are depth-first search and breadth-first search.
- depth-first search: from root to an leaf and then back up toward the root. The search depth is the distance from root to current node.
- breadth-first search: start at the root node and process all elements of each particular depth before go to the nest level.
The Streams API use the depth-first search strategy to traverse a directory. It happens in a lazy manner, which means that the elements are built and read while the directory is being traversed.
To manager circular Path, the NIO.2 API offers the option to inform FOLLOW_LINKS to the walk method and then specify a depth limit. It will track the path visited and throw an exception if a cycle is detected.
Recursively access a directory tree
The DirectoryStream interface (which does not implement or extend the Stream interface) is used to read a single directory. It can be used to iterate over a directory, such as the listFiles method.
The FileVisitor interface is used to visit an entire directory tree. To use this you need implemet the interface and then pass a Files.walkFileTree() method that will handle process to load the next directory and file. If you use Path such the generic type you need four methods: visitFile, visitFileFailed, preVisitDirectory and postVisitDirectory.
When you want to do something simple you can use the SimpleFileVisitor and implement only the necessary methods for your functionality.
Observe the changes in a directory
The NIO.2 API offers the WatchService API for monitoring changes. To use the API you need to create an instance of WatchService, register the directory and event type, create a loop to verify the change, retrieve a WatchKey, retrieve all pending events for the WatchKey and do something, reset WatchKey, close the resource if you do not need the WatchServe.
A complete example you can see in Java Tutorials, this another post show you different ways to use this interface, and the HowToDoInJava post show another great example.
Conclusion
Certainly, the NIO.2 API is a great improvement that helps the files handle. But there is a lot to practices.
A good discussion you can see in the StackOverflow question.
Don’t stop to study. Much other java version is available. Go deeply in your research and pay attention to what the version that you use offer for you.
Related Posts
- Java 8 - Part VII [Collections]
- Java 8 – Part VI [File IO NIO.2]
- Java 8 – Part V [Concurreny]
- Java 8 – Part IV [Streams]
- Java 8 – Parte III [Lambda]
- Java 8 - Part II [Localization, Date, Time]
- Java 8 - Language Enhancements
- JVM