📄 tij314.htm
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html lang="en">
<!--
This document was converted from RTF source:
By r2net 5.8 r2netcmd Windows
See http://www.logictran.com
-->
<head><meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Thinking in Java, 3rd ed. Revision 4.0: 12: The Java I/O System</title>
<link rel="stylesheet" href="stylesheet.css" type="text/css"></head>
<body >
<CENTER> <a href="http://www.MindView.net"> <img src="mindview.gif" alt="MindView Inc." BORDER = "0"></a> <Font FACE="Verdana, Tahoma, Arial, Helvetica, Sans"> <h2>Thinking in Java, 3<sup>rd</sup> ed. Revision 4.0</h2> <FONT size = "-1"><br> [ <a href="README.txt">Viewing Hints</a> ] [ <a href="http://www.mindview.net/Books/TIJ/">Book Home Page</a> ] [ <a href="http://www.mindview.net/Etc/MailingList.html">Free Newsletter</a> ] <br> [ <a href="http://www.mindview.net/Seminars">Seminars</a> ] [ <a href="http://www.mindview.net/CDs">Seminars on CD ROM</a> ] [ <a href="http://www.mindview.net/Services">Consulting</a> ] <br><br> </FONT></FONT> </CENTER>
<font face="Georgia"><div align="CENTER"><a href="TIJ313.htm" target="RightFrame"><img src="./prev.gif" alt="Previous " border="0"></a>
<a href="TIJ315.htm" target="RightFrame"><img src="./next.gif" alt="Next " border="0"></a>
<a href="TIJ3_t.htm"><img src="./first.gif" alt="Title Page " border="0"></a>
<a href="TIJ3_i.htm"><img src="./index.gif" alt="Index " border="0"></a>
<a href="TIJ3_c.htm"><img src="./contents.gif" alt="Contents " border="0"></a>
</div>
<hr>
<h1>
<a name="_Toc375545381"></a><a name="_Toc24272651"></a><a name="_Toc24775783"></a><a name="Heading13843"></a>12:
The Java <br>I/O System</h1>
<p class="Intro">Creating a good input/output (I/O) system is one of the more difficult tasks for the language designer.<br></p>
<p>This is evidenced by the number of different approaches. The challenge seems to be in covering all eventualities. Not only are there different sources and sinks of I/O that you want to communicate with (files, the console, network connections, etc.), but you need to talk to them in a wide variety of ways (sequential, random-access, buffered, binary, character, by lines, by words, etc.). <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap11_1621" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>The Java library designers attacked this problem by creating lots of classes. In fact, there are so many classes for Java’s I/O system that it can be intimidating at first (ironically, the Java I/O design actually prevents an explosion of classes). There was also a significant change in the I/O library after Java 1.0, when the original <a name="Index1162"></a><b>byte</b>-oriented library was supplemented with <b>char</b>-oriented, Unicode-based I/O classes. In JDK 1.4, the <b>nio</b> classes (for “new I/O,” a name we’ll still be using years from now) were added for improved performance and functionality. As a result, there are a fair number of classes to learn before you understand enough of Java’s I/O picture that you can use it properly. In addition, it’s rather important to understand the evolution history of the I/O library, even if your first reaction is “don’t bother me with history, just show me how to use it!” The problem is that without the historical perspective, you will rapidly become confused with some of the classes and when you should and shouldn’t use them. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap11_1622" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>This chapter will give you an introduction to the variety of I/O classes in the standard Java library and how to use them. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap11_1623" title="Send BackTalk Comment">Feedback</a></font><br></p>
<h2>
<a name="_Toc375545382"></a><a name="_Toc375545390"></a><a name="_Toc24775784"></a><a name="Heading13848"></a>The
<b>File</b> class<br></h2>
<p><a name="Index1163"></a><a name="Index1164"></a><a name="Index1165"></a><a name="Index1166"></a><a name="Index1167"></a><a name="Index1168"></a>Before getting into the classes that actually read and write data to streams, we’ll look at a utility provided with the library to assist you in handling file directory issues. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap11_1624" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>The <b>File </b>class has a deceiving name; you might think it refers to a file, but it doesn’t. It can represent either the <i>name</i> of a particular file or the <i>names</i> of a set of files in a directory. If it’s a set of files, you can ask for that set using the <b>list( )</b> method, which returns an array of <b>String</b>. It makes sense to return an array rather than one of the flexible container classes, because the number of elements is fixed, and if you want a different directory listing, you just create a different <b>File</b> object. In fact, “FilePath” would have been a better name for the class. This section shows an example of the use of this class, including the associated <b>FilenameFilter</b> <b>interface</b>. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap11_1625" title="Send BackTalk Comment">Feedback</a></font><br></p>
<h3>
<a name="_Toc375545391"></a><a name="_Toc24775785"></a><a name="Heading13851"></a>A
directory lister<br></h3>
<p><a name="Index1169"></a><a name="Index1170"></a>Suppose you’d like to see a directory listing. The <b>File</b> object can be listed in two ways. If you call <b>list( )</b> with no arguments, you’ll get the full list that the <b>File</b> object contains. However, if you want a restricted list—for example, if you want all of the files with an extension of <b>.java</b>—then you use a “directory filter,” which is a class that tells how to select the <b>File</b> objects for display. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap11_1626" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>Here’s the code for the example. Note that the result has been effortlessly sorted (alphabetically) using the <b>java.utils.Arrays.sort( )</b> method and the <b>AlphabeticComparator</b> defined in Chapter 11:<br></p>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c12:DirList.java</font>
<font color=#009900>// Displays directory listing using regular expressions.</font>
<font color=#009900>// {Args: "D.*\.java"}</font>
<font color=#0000ff>import</font> java.io.*;
<font color=#0000ff>import</font> java.util.*;
<font color=#0000ff>import</font> java.util.regex.*;
<font color=#0000ff>import</font> com.bruceeckel.util.*;
<font color=#0000ff>public</font> <font color=#0000ff>class</font> DirList {
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
File path = <font color=#0000ff>new</font> File(<font color=#004488>"."</font>);
String[] list;
<font color=#0000ff>if</font>(args.length == 0)
list = path.list();
<font color=#0000ff>else</font>
list = path.list(<font color=#0000ff>new</font> DirFilter(args[0]));
Arrays.sort(list, <font color=#0000ff>new</font> AlphabeticComparator());
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < list.length; i++)
System.out.println(list[i]);
}
}
<font color=#0000ff>class</font> DirFilter <font color=#0000ff>implements</font> FilenameFilter {
<font color=#0000ff>private</font> Pattern pattern;
<font color=#0000ff>public</font> DirFilter(String regex) {
pattern = Pattern.compile(regex);
}
<font color=#0000ff>public</font> <font color=#0000ff>boolean</font> accept(File dir, String name) {
<font color=#009900>// Strip path information, search for regex:</font>
<font color=#0000ff>return</font> pattern.matcher(
<font color=#0000ff>new</font> File(name).getName()).matches();
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE><p><br></p>
<p>The <b>DirFilter</b> class “implements” the <b>interface</b> <b>FilenameFilter</b>. It’s useful to see how simple the <b>FilenameFilter</b> <b>interface</b> is: <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap11_1627" title="Send BackTalk Comment">Feedback</a></font><br></p>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#0000ff>public</font> <font color=#0000ff>interface</font> FilenameFilter {
<font color=#0000ff>boolean</font> accept(File dir, String name);
}</PRE></FONT></BLOCKQUOTE><p><br></p>
<p>It says all that this type of object does is provide a method called <b>accept( )</b>. The whole reason behind the creation of this class is to provide the <b>accept( )</b> method to the <b>list( )</b> method so that <b>list( )</b> can “call back” <b>accept( )</b> to determine which file names should be included in the list. Thus, this structure is often referred to as a <a name="Index1171"></a><i>callback</i>. More specifically, this is an example of the <i>Strategy Pattern</i>, because <b>list( )</b> implements basic functionality, and you provide the <i>Strategy</i> in the form of a <b>FilenameFilter</b> in order to complete the algorithm necessary for <b>list( )</b> to provide its service. Because <b>list( )</b> takes a <b>FilenameFilter</b> object as its argument, it means that you can pass an object of any class that implements <b>FilenameFilter</b> to choose (even at run time) how the <b>list( )</b> method will behave. The purpose of a callback is to provide flexibility in the behavior of code. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap11_1628" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p><b>DirFilter</b> shows that just because an <b>interface</b> contains only a set of methods, you’re not restricted to writing only those methods. (You must at least provide definitions for all the methods in an interface, however.) In this case, the <b>DirFilter</b> constructor is also created. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap11_1629" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>The <b>accept( )</b> method must accept a <b>File</b> object representing the directory that a particular file is found in, and a <b>String</b> containing the name of that file. You might choose to use or ignore either of these arguments, but you will probably at least use the file name. Remember that the <b>list( )</b> method is calling <b>accept( )</b> for each of the file names in the directory object to see which one should be included; this is indicated by the <b>boolean</b> result returned by <b>accept( )</b>. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap11_1630" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>To make sure the element you’re working with is only the file name and contains no path information, all you have to do is take the <b>String</b> object and create a <b>File</b> object out of it, then call <b>getName( )</b>, which strips away all the path information (in a platform-independent way). Then <b>accept( )</b> uses a regular expression <b>matcher</b> object to see if the regular expression <b>regex</b> matches the name of the file. Using <b>accept( )</b>, the <b>list( )</b> method returns an array. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap11_1631" title="Send BackTalk Comment">Feedback</a></font><br></p>
<h4>
<a name="Heading13897"></a>Anonymous inner classes</h4>
<p>This example is ideal for rewriting using an anonymous inner class (described in Chapter 8). As a first cut, a method <a name="Index1172"></a><a name="Index1173"></a><a name="Index1174"></a><b>filter( ) </b>is created that returns a reference to a <b>FilenameFilter</b>:<br></p>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c12:DirList2.java</font>
<font color=#009900>// Uses anonymous inner classes.</font>
<font color=#009900>// {Args: "D.*\.java"}</font>
<font color=#0000ff>import</font> java.io.*;
<font color=#0000ff>import</font> java.util.*;
<font color=#0000ff>import</font> java.util.regex.*;
<font color=#0000ff>import</font> com.bruceeckel.util.*;
<font color=#0000ff>public</font> <font color=#0000ff>class</font> DirList2 {
<font color=#0000ff>public</font> <font color=#0000ff>static</font> FilenameFilter filter(<font color=#0000ff>final</font> String regex) {
<font color=#009900>// Creation of anonymous inner class:</font>
<font color=#0000ff>return</font> <font color=#0000ff>new</font> FilenameFilter() {
<font color=#0000ff>private</font> Pattern pattern = Pattern.compile(regex);
<font color=#0000ff>public</font> <font color=#0000ff>boolean</font> accept(File dir, String name) {
<font color=#0000ff>return</font> pattern.matcher(
<font color=#0000ff>new</font> File(name).getName()).matches();
}
}; <font color=#009900>// End of anonymous inner class</font>
}
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
File path = <font color=#0000ff>new</font> File(<font color=#004488>"."</font>);
String[] list;
<font color=#0000ff>if</font>(args.length == 0)
list = path.list();
<font color=#0000ff>else</font>
list = path.list(filter(args[0]));
Arrays.sort(list, <font color=#0000ff>new</font> AlphabeticComparator());
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < list.length; i++)
System.out.println(list[i]);
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE><p><br></p>
<p>Note that the argument to <b>filter( )</b> must be <a name="Index1175"></a><a name="Index1176"></a><b>final</b>. This is required by the anonymous inner class so that it can use an object from outside its scope. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap11_1633" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>This design is an improvement because the <b>FilenameFilter</b> class is now tightly bound to <b>DirList2</b>. However, you can take this approach one step further and define the anonymous inner class as an argument to <b>list( )</b>, in which case it’s even smaller:<br></p>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c12:DirList3.java</font>
<font color=#009900>// Building the anonymous inner class "in-place."</font>
<font color=#009900>// {Args: "D.*\.java"}</font>
<font color=#0000ff>import</font> java.io.*;
<font color=#0000ff>import</font> java.util.*;
<font color=#0000ff>import</font> java.util.regex.*;
<font color=#0000ff>import</font> com.bruceeckel.util.*;
<font color=#0000ff>public</font> <font color=#0000ff>class</font> DirList3 {
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(<font color=#0000ff>final</font> String[] args) {
File path = <font color=#0000ff>new</font> File(<font color=#004488>"."</font>);
String[] list;
<font color=#0000ff>if</font>(args.length == 0)
list = path.list();
<font color=#0000ff>else</font>
list = path.list(<font color=#0000ff>new</font> FilenameFilter() {
<font color=#0000ff>private</font> Pattern pattern = Pattern.compile(args[0]);
<font color=#0000ff>public</font> <font color=#0000ff>boolean</font> accept(File dir, String name) {
<font color=#0000ff>return</font> pattern.matcher(
<font color=#0000ff>new</font> File(name).getName()).matches();
}
});
Arrays.sort(list, <font color=#0000ff>new</font> AlphabeticComparator());
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < list.length; i++)
System.out.println(list[i]);
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE><p><br></p>
<p>The argument to <b>main( )</b> is now <b>final</b>, since the anonymous inner class uses <b>args[0]</b> directly. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap11_1634" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>This shows you how anonymous inner classes allow the creation of specific, one-off classes to solve problems. One benefit of this approach is that it keeps the code that solves a particular problem isolated together in one spot. On the other hand, it is not always as easy to read, so you must use it judiciously. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap11_1635" title="Send BackTalk Comment">Feedback</a></font><br></p>
<h3>
<a name="_Toc375545392"></a><a name="_Toc24775786"></a><a name="Heading13963"></a>Checking
for and creating directories</h3>
<p>The <b>File</b> class is more than just a representation for an existing file or directory. You can also use a <b>File</b> object to create a new directory or an entire directory path if it doesn’t exist. You can also look at the characteristics of files (size, last modification date, read/write), see whether a <a name="Index1177"></a><a name="Index1178"></a><a name="Index1179"></a><a name="Index1180"></a><b>File</b> object represents a file or a directory, and delete a file. This program shows some of the other methods available with the <b>File</b> class (see the HTML documentation from <i>java.sun.com </i>for the full set):<br></p>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c12:MakeDirectories.java</font>
<font color=#009900>// Demonstrates the use of the File class to</font>
<font color=#009900>// create directories and manipulate files.</font>
<font color=#009900>// {Args: MakeDirectoriesTest}</font>
<font color=#0000ff>import</font> com.bruceeckel.simpletest.*;
<font color=#0000ff>import</font> java.io.*;
<font color=#0000ff>public</font> <font color=#0000ff>class</font> MakeDirectories {
<font color=#0000ff>private</font> <font color=#0000ff>static</font> Test monitor = <font color=#0000ff>new</font> Test();
<font color=#0000ff>private</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> usage() {
System.err.println(
<font color=#004488>"Usage:MakeDirectories path1 ...\n"</font> +
<font color=#004488>"Creates each path\n"</font> +
<font color=#004488>"Usage:MakeDirectories -d path1 ...\n"</font> +
<font color=#004488>"Deletes each path\n"</font> +
<font color=#004488>"Usage:MakeDirectories -r path1 path2\n"</font> +
<font color=#004488>"Renames from path1 to path2"</font>);
System.exit(1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -