Enhancements Added to NIO by JDK 7
with JDK 7, the NIO system was substantially expanded and enhanced. In addition
to support for the try-with-resources
statement (which provides automatic resource management), the improvements
included three new packages (java.nio.file,
java.nio.file.attribute, and java.nio.file.spi); several new
classes, interfaces, and methods; and
direct support for stream-based I/O. The additions have greatly expanded the
ways in which NIO can be used, especially with files. Several of the key
additions are described in the following sections.
The Path Interface
the single most important addition to the NIO system is the Path interface because it encapsulates
a path to a file. As you will see, Path
is the glue that binds together many of the NIO.2 file-based features. It
describes a file’s location within the directory structure. Path is packaged in java.nio.file, and it inherits the
following interfaces: Watchable, Iterable<Path>, and Comparable<Path>. Watchable describes an object that can
be monitored for changes. The Iterable
and Comparable interfaces were
described earlier in this book.
Path declares a number of methods that operate on
the path. A sampling is shown in Table
21-3. Pay special attention to the getName(
) method. It is used to obtain an element in a path. It works using an
index. At index zero is the part of the path nearest the root, which is the
leftmost element in a path. Subsequent indexes specify elements to the right of
the root. The number of elements in a path can be obtained by calling getNameCount( ). If you want to obtain
a string representation of the entire path, simply call toString( ). Notice that you can resolve a relative path into an
absolute path by using the resolve( )
endsWith(String path) : Returns true if the invoking Path ends with the path
specified by path. Otherwise, returns false.
endsWith(Path path) : Returns true if the invoking Path ends with the path
specified by path. Otherwise, returns false.
getFileName( ) : Returns the filename associated with the invoking Path.
getName(int idx) : Returns a Path object that contains the name of the path
element specified by idx within the invoking object. The leftmost element is at
index 0. This is the element nearest the root. The rightmost element is at
getNameCount( ) – 1.
getNameCount( ) : Returns the number of elements beyond the root directory in
the invoking Path.
getParent( ) : Returns a Path that contains the entire path except for the name
of the file specified by the invoking Path.
getRoot( ) : Returns the root of the invoking Path.
isAbsolute( ) : Returns true if the invoking Path is absolute. Otherwise,
resolve(Path path) : If path is absolute, path is returned. Otherwise, if path
does not contain a root, path is prefixed by the root specified by the invoking
Path and the result is returned. If path is empty, the invoking Path is
returned. Otherwise, the behavior is unspecified.
resolve(String path) : If path is absolute, path is returned. Otherwise, if
path does not contain a root, path is prefixed by the root specified by the
invoking Path and the result is returned. If path is empty, the invoking Path
is returned. Otherwise, the behavior is unspecified.
startsWith(String path) : Returns true if the invoking Path starts with the
path specified by path. Otherwise, returns false.
startsWith(Path path) : Returns true if the invoking Path starts with the path
specified by path. Otherwise, returns false.
toAbsolutePath( ) : Returns the invoking Path as an absolute path.
toString( ) : Returns a string representation of the invoking Path.
Table 21-3 A Sampling of Methods Specified by Path
other point: When updating legacy code that uses the File class defined by java.io,
it is possible to convert a File
instance into a Path instance by
calling toPath( ) on the File object. Furthermore, it is
possible to obtain a File instance
by calling the toFile( ) method
defined by Path.
The Files Class
the actions that you perform on a file are provided by static methods within the Files
class. The file to be acted upon is specified by its Path. Thus, the Files methods
use a Path to specify the file that
is being operated upon. Files contains
a wide array of functionality. For
example, it has methods that let you open or create a file that has the
specified path. You can obtain information about a Path, such as whether it is executable, hidden, or read-only. Files also supplies methods that let
you copy or move files. A sampling is shown in Table 21-4. In addition to IOException, several other exceptions
are possible. JDK 8 adds these four methods to Files: list( ), walk( ), lines( ), and find( ).
All return a Stream object. These
methods help integrate NIO with the new stream API defined by JDK 8 and
described in Chapter 29.
that several of the methods in Table 21-4 take an argument of type OpenOption. This is an interface that
describes how to open a file. It is implemented by the StandardOpenOption
class, which defines an enumeration that has the values shown in Table 21-5.
Causes output to be written to the end of the file.
Creates the file if it does not already exist.
: Creates the file only if it does not already exist.
: Deletes the file when it is closed.
Causes changes to the file to be immediately written to the physical file.
Normally, changes to a file are buffered by the file system in the interest of
efficiency, being written to the file only as needed.
Opens the file for input operations.
Indicates to the file system that the file is sparse, meaning that it may not
be completely filled with data. If the file system does not support sparse
files, this option is ignored.
Causes changes to the file or its metadata to be immediately written to the
physical file. Normally, changes to a file are buffered by the file system in
the interest of efficiency, being written to the file only as needed.
: Causes a preexisting file opened for output to be reduced to zero length.
Opens the file for output operations.
Table 21-5 The Standard Open Options
The Paths Class
Because Path is an interface, not a class, you
can’t create an instance of Path
directly through the use of a constructor. Instead, you obtain a Path by a calling a method that returns
one. Frequently, you do this by using the get(
) method defined by the Paths
class. There are two forms of get( ).
The one used in this chapter is shown here:
Path get(String pathname, String ... parts)
returns a Path that encapsulates the
specified path. The path can be specified in two ways. First, if parts is not used, then the path must be
specified in its entirety by pathname.
Alternatively, you can pass the path in pieces, with the first part passed in pathname and the subsequent elements
specified by the parts varargs
parameter. In either case, if the path specified is syntactically invalid, get( ) will throw an InvalidPathException.
second form of get( ) creates a Path from a URI. It is shown here: static Path get(URI uri)
The Path corresponding to uri is returned.
important to understand that creating a Path
to a file does not open or create a file. It simply creates an object that
encapsulates the file’s directory path.
The File Attribute Interfaces
with a file is a set of attributes. These attributes include such things as the
file’s time of creation, the time of its last modification, whether the file is
a directory, and its size. NIO organizes file attributes into several different
interfaces. Attributes are represented by a hierarchy of interfaces defined in java.nio.file.attribute. At the top is BasicFileAttributes. It encapsulates
the set of attributes that are commonly found in a variety of file systems. The
methods defined by BasicFileAttributes
are shown in Table 21-6.
creationTime( ) : Returns the time at which the file was created. If creation
time is not provided by the file system, then an implementation-dependent value
fileKey( ) : Returns the file key. If not supported, null is returned.
isDirectory( ) : Returns true if the file represents a directory.
isOther( ) : Returns true if the file is not a file, symbolic link, or a
isRegularFile( ) : Returns true if the file is a normal file, rather than a
directory or symbolic link.
isSymbolicLink( ) : Returns true if the file is a symbolic link.
lastAccessTime( ) : Returns the time at which the file was last accessed. If
the time of last access is not provided by the file system, then an
implementation- dependent value is returned.
lastModifiedTime( ) : Returns the time at which the file was last modified. If
the time of last modification is not provided by the file system, then an
implementation-dependent value is returned.
size( ) : Returns the size of the file.
Table 21-6 The Methods Defined by BasicFileAttributes
From BasicFileAttributes two interfaces are
derived: DosFileAttributes and
PosixFileAttributes. DosFileAttributes describes those attributes related to the FAT file system as first defined by DOS.
It defines the methods shown here:
Method : Description
isArchive( ) : Returns true if the file is flagged for archiving and false
isHidden( ) : Returns true if the file is hidden and false otherwise.
isReadOnly( ) : Returns true if the file is read-only and false otherwise.
isSystem( ) : Returns true if the file is flagged as a system file and false
PosixFileAttributes encapsulates attributes
defined by the POSIX standards. (POSIX stands for Portable Operating
System Interface.) It defines the methods shown here:
group( ) : Returns the file’s group owner.
owner( ) : Returns the file’s owner.
permissions( ) : Returns the file’s permissions.
are various ways to access a file’s attributes. First, you can obtain an object
that encapsulates a file’s attributes by calling readAttributes( ), which is a static
method defined by Files. One of its
forms is shown here:
<A extends BasicFileAttributes>
LinkOption... opts) throws
method returns a reference to an object that specifies the attributes
associated with the file passed in path.
The specific type of attributes is specified as a Class object in the attrType
parameter. For example, to obtain the basic file attributes, pass BasicFileAttributes.class to attrType. For DOS attributes, use DosFileAttributes.class,
and for POSIX attributes, use PosixFileAttributes.class. Optional
link options are passed via opts. If not specified, symbolic links are followed. The method returns
a reference to requested attributes. If the requested attribute type is not
is thrown. Using the object returned, you can access the file’s attributes.
way to gain access to a file’s attributes is to call getFileAttributeView( ) defined by Files. NIO defines several attribute view interfaces, including AttributeView,
BasicFileAttributeView, DosFileAttributeView, and
PosixFileAttributeView, among others.
Although we won’t be using attribute views in this chapter, they are a
feature that you may find helpful in some situations.
cases, you won’t need to use the file attribute interfaces directly because the
Files class offers static convenience methods that access
several of the attributes. For example,
Files includes methods such as isHidden( ) and isWritable(
important to understand that not all file systems support all possible
attributes. For example, the DOS file attributes apply to the older FAT file
system as first defined by DOS. The attributes that will apply to a wide
variety of file systems are described by BasicFileAttributes.
For this reason, these attributes are used in the examples in this chapter.
The FileSystem, FileSystems, and FileStore
easily access the file system through the FileSystem
and FileSystems classes packaged in java.nio.file. In fact, by using the newFileSystem( ) method defined by FileSystems, it is even possible to
obtain a new file system. The FileStore
class encapsulates the file storage system. Although these classes are not used
directly in this chapter, you may find them helpful in your own applications.