Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Ganesh_JavaSE7_Programming_1z0-804_study_guide.pdf
Скачиваний:
94
Добавлен:
02.02.2015
Размер:
5.88 Mб
Скачать

chapter 9 Java File I/O (NIO.2)

The File class defined many methods that returned a Boolean value. Thus, in case of an error, false was returned, rather than throwing an exception, so the developer had no way of knowing why that call failed.

The File class did not provide good support for handling symbolic links.

The File class handled directories and paths in an inefficient way (it did not scale well).

The File class provided access to a very limited set of file attributes, which was insufficient in many situations.

To overcome these problems, Java introduced NIO (New IO) in Java 4. The key features of NIO were:

Channels and Selectors: NIO offered support for various types of channels. A channel is an abstraction over lower-level file system features (such as memory-mapped files and file locking) that lets you transfer data at a faster speed. Channels are non-blocking, so Java provides another feature—a selector—to select a ready channel for data transfer. A socket is a blocking feature whereas a channel is a non-blocking feature.

Buffers: Java 4 introduced buffering for all primitive classes (except for Boolean). It provided the Buffer class that offers operations such as clear, flip, mark, reset, and rewind. Concrete classes (subclasses of the Buffer base class) offers getters and setters for setting and getting data to and from a buffer.

Charset: Java 4 also introduced charset (java.nio.charset), encoders, and decoders to map bytes and Unicode symbols.

With SE 7 version, Java has introduced comprehensive support for I/O operations. Java 7 introduces the java.nio.file package for better support for handling symbolic links, to provide comprehensive attribute access, and to support the extended file system through interfaces or classes such as Path, Paths, and Files. You will explore these topics in more detail in the rest of this chapter.

Using the Path Interface

File systems usually form a tree. The file system starts with a root directory that contains files and directories (directories are also called folders in Windows). Each directory, in turn, may have subdirectories or hold files. To locate a file, you just need to put together the directories from the root directory to the immediate directory

containing the file, along with a file separator, trailing with the file name. For instance, if the myfile.txt file resides in a mydocs directory, which resides in root directory C:\, then the path of the file is C:\mydocs\myfile.txt. Every file has a unique path to locate it (apart from symbolic links).

A path could be an absolute path (such as C:\mydocs\myfile.txt), which starts from a root element. On the other hand, a path could be specified as a relative path. When you try to compile a Java program, you just write something like javac programFileName.java; here, you have specified the Java source file path relative to the currently selected directory, so this path is a relative path. You need a reference path (such as current directory path in this case) to interpret a relative path.

Before we proceed further, it is relevant to talk about symbolic links. A symbolic link is like a pointer or reference for the actual file. In general, symbolic links are transparent to the applications, which means the operations

are performed directly on the actual files rather than these links (except, of course, for the symbolic link-specific operations).

252

chapter 9 Java File I/O (NIO.2)

Java 7 introduces a new programming abstraction for path, namely the Path interface. This Path abstraction is used in new features and APIs throughout NIO.2, so it is an important interface to understand. A path object contains the names of directories and files that make the full path of the file/directory represented by the Path object; the Path abstraction provides methods to extract path elements, manipulate them, and append them. In fact, you will see later that almost all of the methods that access files/directories to get information about them or manipulate them use Path objects. Before you see a few examples illustrating how to use the Path interface, Table 9-1 quickly summarizes important methods in this interface.

Table 9-1.  Important Methods in the Path Interface

 

 

 

Method

Description

Path getRoot()

Returns a Path object representing the root of the given path,

 

or null if the path does not have a root.

Path getFileName()

Returns the file name or directory name of the given path. Note

 

that the file/directory name is the last element or name in the

 

given path.

Path getParent()

Returns the Path object representing the parent of the given

 

path, or null if no parent component exists for the path.

int getNameCount()

Returns the number of file/directory names in the given path;

 

returns 0 if the given path represents the root.

Path getName(int index)

Returns the ith file/directory name; the index 0 starts from

 

closest name to the root.

Path subpath(int beginIndex, int endIndex)

Returns a Path object that is part of this Path object; the

 

returned Path object has a name that begins at beginIndex

 

till the element at index endIndex - 1. In other words,

 

beginIndex is inclusive of the name in that index and

 

exclusive of the name in endIndex. This method may throw

 

IllegalArgumentException if beginIndex is >= number of

 

elements, or endIndex <= beginIndex, or endIndex is > number

 

of elements.

Path normalize()

Removes redundant elements in path such as . (dot symbol

 

that indicates current directory) and .. (double dot symbol that

 

indicates parent directory).

Path resolve(Path other)

Resolves a path against the given path. For example, this

Path resolve(String other)

method could combine the given path with the other path and

 

return the resulting path.

Boolean isAbsolute()

Returns true if the given path is an absolute path; returns false

 

if not (when the given path is a relative path, for example).

Path startsWith(String path)

Returns true if this Path object starts with the given path, or

Path startsWith(Path path)

else returns false.

Path toAbsolutePath()

Returns the absolute path.

 

 

253

chapter 9 Java File I/O (NIO.2)

Getting Path Information

Let’s create a Path object and retrieve the basic information associated with the object. Listing 9-1 shows how to create a Path object and get information about it.

Listing 9-1.  PathInfo1.java

import java.nio.file.*;

// Class to illustrate how to use Path interface and its methods public class PathInfo1 {

public static void main(String[] args) {

// create a Path object by calling static method get() in Paths class Path testFilePath = Paths.get("D:\\test\\testfile.txt");

// retrieve basic information about path System.out.println("Printing file information: "); System.out.println("\t file name: " + testFilePath.getFileName()); System.out.println("\t root of the path: " + testFilePath.getRoot());

System.out.println("\t parent of the target: " + testFilePath.getParent());

// print path elements

System.out.println("Printing elements of the path: "); for(Path element : testFilePath) {

System.out.println("\t path element: " + element);

}

}

}

The program prints the following:

Printing file information:

file name: testfile.txt root of the path: D:\

parent of the target: D:\test Printing elements of the path:

path element: test

path element: testfile.txt

The output is self explanatory. Let’s understand the program.

First, you create a Path instance using the get() method of the Paths class. The get() method expects a string representing a path as an input. This is the easiest way to create a Path object.

Note that you use an escape character, \, in Paths.get("D:\\test\\testfile.txt"). Without that, \t would mean a tab character, and if you run the program, you’ll get a java.nio.file.InvalidPathException since you cannot have tab characters in path names.

Then, you extract the file name represented by this Path object using the getFilename() method of the Path object.

You also use getRoot() to get the root element of the Path object and parent directory of the target file using the getParent() method.

254

chapter 9 Java File I/O (NIO.2)

You iterate the elements in the path using a foreach loop. Alternatively, you can use getNameCount() to get the number of elements or names in the path and use getName(index) to iterate and access elements/names one by one.

Now, let’s try another example. In this example, you will explore some interesting aspects of a Path object such as how to get an absolute path from a relative path and how you can normalize a path.

Before looking at the example, you need to first understand the methods used in the example:

The toUri() method returns the URI (a path that can be opened from a browser) from the path.

The toAbsolutePath() method returns the absolute path from a given relative path. In case the input path is already an absolute path, the method returns the same object.

The normalize() method performs normalization on the input path. In other words, it removes unnecessary symbols (such as “ . ” and “ .. ”) from the Path object.

toRealPath() is an interesting method. It returns an absolute path from the input path object (as toAbsolutePath()). Also, it normalizes the path (as in normalize()). Further, if linking options are chosen properly, it resolves symbolic links also. However, to succeed with this method, it is necessary that the target file/directory exists in the file system, which is not a prerequisite for other Path methods.

Now, let’s take a look at the example in Listing 9-2. Assume that the file name Test does not exist in your file system.

Listing 9-2.  PathInfo2.java

import java.io.IOException; import java.nio.file.*;

// To illustrate important methods such as normalize(), toAbsolutePath(), and toReativePath() class PathInfo2 {

public static void main(String[] args) throws IOException { //get a path object with relative path

Path testFilePath = Paths.get(".\\Test");

System.out.println("The file name is: " + testFilePath.getFileName()); System.out.println("It's URI is: " + testFilePath.toUri()); System.out.println("It's absolute path is: " + testFilePath.toAbsolutePath()); System.out.println("It's normalized path is: " + testFilePath.normalize());

// get another path object with normalized relative path

Path testPathNormalized = Paths.get(testFilePath.normalize().toString()); System.out.println("It's normalized absolute path is: " +

testPathNormalized.toAbsolutePath());

System.out.println("It's normalized real path is: " + testFilePath.toRealPath (LinkOption.NOFOLLOW_LINKS));

}

}

In our machine it printed the following:

The file name is: Test

It's URI is: file:///D:/OCPJP7/programs/NIO2/./Test

It's absolute path is: D:\OCPJP7\programs\NIO2\.\Test

It's normalized path is: Test

255

chapter 9 Java File I/O (NIO.2)

It's normalized absolute path is: D:\OCPJP7\programs\NIO2\Test

Exception in thread "main" java.nio.file.NoSuchFileException: D:\OCPJP7\programs\NIO2\Test at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:79) [. . . stack trace elided . . .]

at PathInfo2.main(PathInfo2.java:16)

Depending on the directory in which you run this program, the directory path will be different for you. In this program you instantiated a Path object using a relative path. The method getFileName() returns the target file name, as you just saw in the last example. The getUri() method returns the URI, which can be used with browsers, and

the toAbsolutePath() method returns the absolute path of the given relative path. (Note that we are executing the program from the "D:/OCPJP7/programs/NIO2/" folder, hence it becomes the current working directory and therefore it appears in the absolute path and URI.)

You call the normalize() method to remove redundant symbols from the path, so the normalize() method removes the leading dot (In many operating systems, the “.” (single dot) symbol represents the current directory and “..” (double dot) represents parent directory). You then instantiate another Path object using normalized output and print the absolute path again. Finally, you try to call toRealpath(); however, you get an exception (NoSuchFileException). Why? Because, you have not created the Test directory in the current working directory.

Now, let’s create a Test directory in the D:/OCPJP7/programs/NIO2/ directory and run this example again. We got the following output:

The file name is: Test

It's URI is: file:///D:/OCPJP7/programs/NIO2/./Test/ It's absolute path is: D:\OCPJP7\programs\NIO2\.\Test It's normalized path is: Test

It's normalized absolute path is: D:\OCPJP7\programs\NIO2\Test It's normalized real path is: D:\OCPJP7\programs\NIO2\Test

Now, the last call toRealPath() works fine and returns the absolute normalized path.

Path provides many other useful methods, and some of them are listed in Table 9-1. To give an example, here’s how to use the resolve() method:

Path dirName = Paths.get("D:\\OCPJP7\\programs\\NIO2\\"); Path resolvedPath = dirName.resolve("Test"); System.out.println(resolvedPath);

This code segment prints the following:

D:\OCPJP7\programs\NIO2\Test

This resolve() method considers the given path to be a directory and joins (i.e., resolves) the passed path with it, as shown in this example.

The toPath() method in the java.io.File class returns the Path object; this method was added in Java 7. Similarly, you can use the toFile() method in the Path interface to get a File object.

256

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]