package com.mrbool.java7.nio2; import java.nio.file.*; import java.nio.file.attribute.*; import java.text.*; import java.util.*; public class ExampleNio2_Attributes { public static void main(String[] args) throws Exception { FileSystem fs = FileSystems.getDefault(); Properties props = System.getProperties(); String homePath = props.get("user.home").toString(); Path home = fs.getPath(homePath); System.out.println("File\t\t\tCreation Date\t\tLast Access\t\tLast Update"); try (DirectoryStream<Path> flow = Files.newDirectoryStream(home, "*.txt")) { for (Path item : flow) { BasicFileAttributes attrs = Files.readAttributes(item, BasicFileAttributes.class); Date creationDate = new Date(attrs.creationTime().toMillis()); Date accessDate = new Date(attrs.lastAccessTime().toMillis()); Date updateDate = new Date(attrs.lastModifiedTime().toMillis()); DateFormat df = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss"); System.out.format("%s\t%s\t%s\t%s%n", item, df.format(creationDate), df.format(accessDate), df.format(updateDate)); } } } }

package com.mrbool.java7.nio2; import java.io.IOException; import java.nio.file.*; import java.nio.file.attribute.BasicFileAttributes; public class ExampleNio2_Navigating { public static void main(String[] args) throws Exception { if (args.length != 1) System.out.println("Use: java ExampleNio2_Navigating <directory>"); Path root = Paths.get(args[0]); CalculateFileSizeVisitor visitor = new CalculateFileSizeVisitor(); Files.walkFileTree(root, visitor); System.out.format("The given directory contains %d files spred in %d directories, occupying %.4f MB in disk", visitor.numFiles, visitor.numDirs, visitor.sizeSum / (1024.0 * 1024)); } } class CalculateFileSizeVisitor implements FileVisitor<Path> { int numFiles = 0; int numDirs = 0; long sizeSum = 0; @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { System.out.println("[D] " + dir); numDirs++; return FileVisitResult.CONTINUE; } @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { System.out.println("[F]\t " + file); sizeSum += attrs.size(); numFiles++; return FileVisitResult.CONTINUE; } @Override public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { System.err.println("It was not possible to analyze the file: " + file); return FileVisitResult.TERMINATE; } @Override public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { return FileVisitResult.CONTINUE; } }

package com.mrbool.java7.nio2; import java.nio.file.*; import java.util.Properties; public class ExampleNio2_Monitoring { public static void main(String[] args) throws Exception { FileSystem fs = FileSystems.getDefault(); WatchService ws = fs.newWatchService(); Properties props = System.getProperties(); String homePath = props.get("user.home").toString(); Path home = fs.getPath(homePath); home.register(ws, StandardWatchEventKinds.ENTRY_CREATE); System.out.println("Monitoring file creation in " + home + "... (Ctrl+C to quit)"); while (true) { WatchKey key = ws.take(); for (WatchEvent<?> event : key.pollEvents()) { if (event.kind() == StandardWatchEventKinds.ENTRY_CREATE) { Path item = (Path)event.context(); System.out.println("Created: " + item); } } key.reset(); } } }

Since its earlier versions, Java was already capable of manipulating files. However, until Java 6 there were several limitations with the API provided by the JVM in package, for instance:• There is no single operation to copy a file to another location. When necessary, it has to be implemented using data flows (like one of the examples in the previous article in this series);• Support to file attributes (creation date, last update date, permissions to read/write, executable flag, etc.) is limited;• It's not 100% consistent throughout the different platforms supported by Java;• Often, exceptions thrown due to failures during file operations are not very useful;• It's not possible to extend the API to support a new type of file system.To address these limitations, JSR 203 – More New I/O APIs for the JavaTM Platform (“NIO.2”) was proposed. This extension was called “NIO.2” because since Java 1.4 the packageis already present, supporting the creation of I/O channels. Channels are objects that represent a connection with a generic resource that is capable of executing I/O operations, such as files and network sockets.The NIO.2 API adds three subpackages tomain package for NIO.2, defines interfaces and classes to access files and file systems using the new API;contains classes and interfaces related to reading and changing file attributes;contains service provider interfaces for NIO.2, to be used by developers who wish the implement support to a new type of file system.(If you want to learn more about Java, go to our Java online courses The following classes (from package) represent the main concepts of the new API:immutable class that represents the path to any file, like, for instance,orclass that contains severalmethods for the execution of operations in files given their paths;class that represents the file system as a whole, used to obtain paths to files;class that contains severalmethods for obtaining a file system. The methodobtains an object that allows us to access all files to which the JVM has access;class that represents the file storing mechanism that is manipulated by the different methods of the API (a partition of a hard drive, an external device plugged in via USB, etc.).The new API comes with many new functionalities, addressing the limitations of the old API that have been presented in the beginning of the article. To give an idea of how these new NIO.2 features work, we selected four of them for our demonstrations: glob filtering, file attribute manipulation, recursive navigation in directory trees and event monitoring.Glob filtering is a pattern matching solution used in command interpreters like the Linux console (e.g., bash) or the Windows command prompt (cmd.exe). In this type of filtering, a question mark () represents any single character whereas a star (*) represents any number of characters. These special characters are called wildcards. Now, with NIO.2 it's possible to filter contents in directories using glob filtering, as shown inUsing NIO.2 to list the files with .txt extension and their dates of creation, last access and last update.The example starts by obtaining the system property, which contains a string that represents the path to the user's base directory (e.g.,in Linux,in Windows 7, etc.). In case you prefer to use a different directory for this test, just set thevariable to the path to the directory you want. For instance, in a Windows system it could be:".Thevariable is then used to create an instance of class, which represents the path to the folder in question. With this object at hand, it's possible to use the methods of the Files class to copy, move, create files/directories/links, delete, check for existence, etc. In the example of, however, we use the methodto create a flow of information from a directory, which allows us to analyze the files and subdirectories present in that folder. Notice also that:(a) Glob filtering was used in the creation of the information flow, specifying that it should return only items that end in the .txt extension;(b) The try with closeable resources feature from Project Coin, presented in an earlier article in this series, was used to automatically close the flow at the end of the block.With the flow open, it's possible to iterate through it with a for-each loop, manipulating all files with the .txt extension that are inside the given directory. At this point,presents the second feature mentioned earlier: manipulation of file attributes. The methodis used to obtain an object of class, which contains basic file attributes that are present in most operating systems: date/time of creation, last access and last update, if the path points to a file, directory, link or other and the size of the file in bytes. Two other interfaces are available to be used in this situation:and, with specific attributes for DOS-based systems (i.e., different versions of Windows) and POSIX-based systems (Unix, Linux, MacOS X, among others), respectivelly.Another feature of NIO.2 demonstrated in this article is the recursive navigation through a tree of directories. Java 7 brings a mini-framework for efficient depth-first navigation given aobject that represents the starting (root) directory.shows an example. Note that in this example the initialobject is obtained in a different way than what was done previously in: instead of obtaining the default, we use the shortcut(highlighted in bold).Navigating through an entire directory tree with NIO.2.To navigate a directory, all we need to use is to call the method, specifying theobject that points to the folder to be navigated and an instance ofthat indicates what should be done to each file and subdirectory found during navigation. For this second parameter, a new class –– was defined, implementing the required interface.This new class then overrides the methods defined in the interface, which are called by NIO.2 during the recursive navigation. These methods are:executed for each directory found, before its contents are analyzed. Receives as parameter theobject that points to the folder and an object containing its basic attributes;executed for each file found. Receives theobject that represents the file and also an object containing its attributes;executed in case it's not possible to access a given file (for instance, because you lack the necessary permissions). Receives theobject that points to the file and an exception () that indicates the failure that occurred;executed for each directory, after its contents were analyzed. Receives theobject representing the folder and a second parameter that has two possible values: null, in case the processing of the directory occurred without errors, or an exception otherwise.All four methods should return an instance of, an enumerated type that defines what to do at the end of the execution of the method:proceed normally;interrupt the recursive navigation;if used in themethod, continues the navigation but skips the folder currently being analyzed;continues the navigation, but does not analyze any other files or subdirectories contained in the same folder as the current item (i.e., its siblings).In the example, theclass calculates the number of existing files and directories and the total size occupied by the files. Furthermore, it prints on standard output each directory () and file () analyzed. At the end of the program, the calculated values are also printed.Finally, the last functionality from NIO.2 presented in this article is the ability of monitoring events from the file system, like creation, update and deletion of files and directories.shows how to monitor for the creation of new files in the user's home directory.Monitoring file creation events with NIO.2First of all, it's necessary to register to the event in question, which is done thought themethod of theobject that we intend to monitor (in the example, the variable home). In this method, we should specify a monitoring service (obtained from thewith the method) and the kind of event to monitor (use one of the static variables present in class).After registering for the event, all we need to do is call themethod from the monitoring service to block the current thread and wait for some event to happen. Once this occurs, NIO.2 returns from this method with an instance of, which can be used to navigate through all the events that occurred while the thread was suspended. Each event contained in this object brings as an attribute the type of event and the file/directory to which the event refers. In the example of, every time a file or directory is created in the user's home folder, the program prints the name of the created item on screen.Putting this code in some kind of loop (the example uses an infinite loop and, therefore, the program should be interrupted with Ctrl+C or will execute indefinitely), you will also need totheinstance after processing events, otherwise future events will not be sent to the thread.Beyond the functionalities exemplified in this article, three other characteristics of NIO.2 are worthy of special note:the API contains a complete support to symbolic links, treating them as if they were the file or directory to which they refer. As a consequence, for instance, comparing aobject that represents a link with theobject that points to the same file/folder as the link itself with methodshould return. The only methods that are an exception to this rule are deletion methods (delete the link and no the referred file), motion (move the link, not the file) and, which does not navigate into directories pointed by links;in case you need to mixcode with NIO.2, it's possible to create aobject from aobject –– and vice-versa –NIO.2 can be extended to handle other types of file systems to which support is not yet given. As a proof of concept, JDK 7 brings among its examples aimplementation for ZIP files, which allows us to manipulate contents of compressed archives transparently, as if they were files directly in the file system. For example, if p1 is aobject obtained from the ZIP file system andfrom the default file system, the operationwill copy the file from the compressed archive, automatically decompressing it, to the default file system. Decompression is provided by the ZIP file system implementation.