📄 chapter17.html
字号:
<font color=#004488>"version of Tjava.doc sources into "</font> +
<font color=#004488>"directories off current directory\n"</font> +
<font color=#004488>"java CodePackager packedFileName newDir\n"</font> +
<font color=#004488>"Extracts into directories off newDir\n"</font> +
<font color=#004488>"java CodePackager -p source.txt packedFile"</font> +
<font color=#004488>"\nCreates packed version of source files"</font> +
<font color=#004488>"\nfrom text version of Tjava.doc"</font>;
<font color=#0000ff>private</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> usage() {
System.err.println(usageString);
System.exit(1);
}
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
<font color=#0000ff>if</font>(args.length == 0) usage();
<font color=#0000ff>if</font>(args[0].equals(<font color=#004488>"-p"</font>)) {
<font color=#0000ff>if</font>(args.length != 3)
usage();
createPackedFile(args);
}
<font color=#0000ff>else</font> {
<font color=#0000ff>if</font>(args.length > 2)
usage();
extractPackedFile(args);
}
}
<font color=#0000ff>private</font> <font color=#0000ff>static</font> String currentLine;
<font color=#0000ff>private</font> <font color=#0000ff>static</font> BufferedReader in;
<font color=#0000ff>private</font> <font color=#0000ff>static</font> DirMap dm;
<font color=#0000ff>private</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font>
createPackedFile(String[] args) {
dm = <font color=#0000ff>new</font> DirMap();
in = IO.disOpen(args[1]);
<font color=#0000ff>try</font> {
<font color=#0000ff>while</font>((currentLine = in.readLine())
!= <font color=#0000ff>null</font>) {
<font color=#0000ff>if</font>(currentLine.startsWith(
SourceCodeFile.startMarker)) {
dm.add(<font color=#0000ff>new</font> SourceCodeFile(
currentLine, in));
}
<font color=#0000ff>else</font> <font color=#0000ff>if</font>(currentLine.startsWith(
SourceCodeFile.endMarker))
Pr.error(<font color=#004488>"file has no start marker"</font>);
<font color=#009900>// Else ignore the input line</font>
}
} <font color=#0000ff>catch</font>(IOException e) {
Pr.error(<font color=#004488>"Error reading "</font> + args[1]);
}
IO.close(in);
dm.writePackedFile(args[2]);
}
<font color=#0000ff>private</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font>
extractPackedFile(String[] args) {
<font color=#0000ff>if</font>(args.length == 2) <font color=#009900>// Alternate directory</font>
dm = <font color=#0000ff>new</font> DirMap(args[1]);
<font color=#0000ff>else</font> <font color=#009900>// Current directory</font>
dm = <font color=#0000ff>new</font> DirMap();
in = IO.disOpen(args[0]);
String s = <font color=#0000ff>null</font>;
<font color=#0000ff>try</font> {
s = in.readLine();
} <font color=#0000ff>catch</font>(IOException e) {
Pr.error(<font color=#004488>"Cannot read from "</font> + in);
}
<font color=#009900>// Capture the separator used in the system</font>
<font color=#009900>// that packed the file:</font>
<font color=#0000ff>if</font>(s.indexOf(<font color=#004488>"###Old Separator:"</font>) != -1 ) {
String oldsep = s.substring(
<font color=#004488>"###Old Separator:"</font>.length());
oldsep = oldsep.substring(
0, oldsep. indexOf('#'));
SourceCodeFile.oldsep = oldsep;
}
SourceCodeFile sf = <font color=#0000ff>new</font> SourceCodeFile(in);
<font color=#0000ff>while</font>(sf.hasFile()) {
dm.add(sf);
sf = <font color=#0000ff>new</font> SourceCodeFile(in);
}
dm.write();
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You’ll first notice the
<B>package</B> statement that is commented out. Since this is the first program
in the chapter, the <B>package </B>statement is necessary to tell
<B>CodePackager </B>that the chapter has changed, but putting it in a package
would be a problem. When you create a <B>package</B>, you tie the resulting
program to a particular directory structure, which is fine for most of the
examples in this book. Here, however, the <B>CodePackager</B> program must be
compiled and run from an arbitrary directory, so the <B>package</B> statement is
commented out. It will still <I>look</I> like an ordinary <B>package</B>
statement to <B>CodePackager</B>, though, since the program isn’t
sophisticated enough to detect multi-line comments. (It has no need for such
sophistication, a fact that comes in handy here.)</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The first two classes are
support/utility classes designed to make the rest of the program more consistent
to write and easier to read. The first, <B>Pr</B>, is similar to the ANSI C
library <B>perror</B>, since it prints an error message (but also exits the
program). The second class encapsulates the creation of files, a process that
was shown in Chapter 10 as one that rapidly becomes verbose and annoying. In
Chapter 10, the proposed solution created new classes, but here <B>static
</B>method calls are used. Within those methods the appropriate exceptions are
caught and dealt with. These methods make the rest of the code much cleaner to
read.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The first class that helps solve
the problem is <B>SourceCodeFile</B>, which represents all the information
(including the contents, file name, and directory) for one source code file in
the book. It also contains a set of <B>String</B> constants representing the
markers that start and end a file, a marker used inside the packed file, the
current system’s end-of-line separator and file path separator (notice the
use of <B>System.getProperty( )</B> to get the local version), and a
copyright notice, which is extracted from the following file
<B>Copyright.txt</B>.</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//////////////////////////////////////////////////</font>
<font color=#009900>// Copyright (c) Bruce Eckel, 1998</font>
<font color=#009900>// Source code file from the book "Thinking in Java"</font>
<font color=#009900>// All rights reserved EXCEPT as allowed by the</font>
<font color=#009900>// following statements: You may freely use this file</font>
<font color=#009900>// for your own work (personal or commercial),</font>
<font color=#009900>// including modifications and distribution in</font>
<font color=#009900>// executable form only. Permission is granted to use</font>
<font color=#009900>// this file in classroom situations, including its</font>
<font color=#009900>// use in presentation materials, as long as the book</font>
<font color=#009900>// "Thinking in Java" is cited as the source. </font>
<font color=#009900>// Except in classroom situations, you may not copy</font>
<font color=#009900>// and distribute this code; instead, the sole</font>
<font color=#009900>// distribution point is http://www.BruceEckel.com </font>
<font color=#009900>// (and official mirror sites) where it is</font>
<font color=#009900>// freely available. You may not remove this</font>
<font color=#009900>// copyright and notice. You may not distribute</font>
<font color=#009900>// modified versions of the source code in this</font>
<font color=#009900>// package. You may not use this file in printed</font>
<font color=#009900>// media without the express permission of the</font>
<font color=#009900>// author. Bruce Eckel makes no representation about</font>
<font color=#009900>// the suitability of this software for any purpose.</font>
<font color=#009900>// It is provided "as is" without express or implied</font>
<font color=#009900>// warranty of any kind, including any implied</font>
<font color=#009900>// warranty of merchantability, fitness for a</font>
<font color=#009900>// particular purpose or non-infringement. The entire</font>
<font color=#009900>// risk as to the quality and performance of the</font>
<font color=#009900>// software is with you. Bruce Eckel and the</font>
<font color=#009900>// publisher shall not be liable for any damages</font>
<font color=#009900>// suffered by you or any third party as a result of</font>
<font color=#009900>// using or distributing software. In no event will</font>
<font color=#009900>// Bruce Eckel or the publisher be liable for any</font>
<font color=#009900>// lost revenue, profit, or data, or for direct,</font>
<font color=#009900>// indirect, special, consequential, incidental, or</font>
<font color=#009900>// punitive damages, however caused and regardless of</font>
<font color=#009900>// the theory of liability, arising out of the use of</font>
<font color=#009900>// or inability to use software, even if Bruce Eckel</font>
<font color=#009900>// and the publisher have been advised of the</font>
<font color=#009900>// possibility of such damages. Should the software</font>
<font color=#009900>// prove defective, you assume the cost of all</font>
<font color=#009900>// necessary servicing, repair, or correction. If you</font>
<font color=#009900>// think you've found an error, please email all</font>
<font color=#009900>// modified files with clearly commented changes to:</font>
<font color=#009900>// Bruce@EckelObjects.com. (please use the same</font>
<font color=#009900>// address for non-code errors found in the book).</font>
<font color=#009900>//////////////////////////////////////////////////</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">When extracting files from a packed
file, the file separator of the system that packed the file is also noted, so it
can be replaced with the correct one for the local system.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The subdirectory name for the
current chapter is kept in the field <B>chapter</B>, which is initialized to
<B>c02</B>. (You’ll notice that the listing in Chapter 2 doesn’t
contain a package statement.) The only time that the <B>chapter</B> field
changes is when a <B>package</B> statement is discovered in the current
file.</FONT><BR></P></DIV>
<A NAME="Heading573"></A><FONT FACE = "Verdana"><H4 ALIGN="LEFT">
Building a packed file</H4></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The first constructor is used to
extract a file from the ASCII text version of this book. The calling code (which
appears further down in the listing) reads each line in until it finds one that
matches the beginning of a listing. At that point, it creates a new
<B>SourceCodeFile</B> object, passing it the first line (which has already been
read by the calling code) and the
<A NAME="Index3010"></A><A NAME="Index3011"></A><B>BufferedReader</B> object
from which to extract the rest of the source code listing.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">At this point, you begin to see
heavy use of the <B>String</B> methods. To extract the file name, the overloaded
version of
<A NAME="Index3012"></A><A NAME="Index3013"></A><B>substring( )</B> is
called that takes the starting offset and goes to the end of the <B>String</B>.
This starting index is produced by finding the
<A NAME="Index3014"></A><A NAME="Index3015"></A><B>length( )</B> of the
<B>startMarker</B>.<B>
<A NAME="Index3016"></A><A NAME="Index3017"></A>trim( )</B> removes white
space from both ends of the <B>String</B>. The first line can also have words
after the name of the file; these are detected using
<A NAME="Index3018"></A><A NAME="Index3019"></A><B>indexOf( )</B>, which
returns -1 if it cannot find the character you’re looking for and the
value where the first instance of that character is found if it does. Notice
there is also an overloaded version of <B>indexOf( )</B> that takes a
<B>String</B> instead of a character.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Once the file name is parsed and
stored, the first line is placed into the <B>contents</B> <B>String</B> (which
is used to hold the entire text of the source code listing). At this point, the
rest of the lines are read and concatenated into the <B>contents</B>
<B>String</B>. It’s not quite that simple, since certain situations
require special handling. One case is error checking: if you run into a
<B>startMarker</B>, it means that no end marker was placed at the end of the
listing that’s currently being collected. This is an error condition that
aborts the program.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The second special case is the
<B>package</B> keyword. Although Java is a free-form language, this program
requires that the <B>package</B> keyword be at the beginning of the line. When
the <B>package</B> keyword is seen, the package name is extracted by looking for
the space at the beginning and the semicolon at the end. (Note that this could
also have been performed in a single operation by using the overloaded
<B>substring( )</B> that takes both the starting and ending indexes.) Then
the dots in the package name are replaced by the file separator, although an
assumption is made here that the file separator is only one character long. This
is probably true on all systems, but it’s a place to look if there are
problems.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The default behavior is to
concatenate each line to <B>contents</B>, along with the end-of-line string,
until the <B>endMarker</B> is discovered, which indicates that the constructor
should terminate. If the end of the file is encountered before the
<B>endMarker</B> is seen, that’s an error.</FONT><BR></P></DIV>
<A NAME="Heading574"></A><FONT FACE = "Verdana"><H4 ALIGN="LEFT">
Extracting from a packed file</H4></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The second constructor is used to
recover the source code files from a packed file. Here, the calling method
doesn’t have to worry about skipping over the intermediate text. The file
contains all the source-code files, placed end-to-end. All you need to hand to
this constructor is the <B>BufferedReader</B> where the information is coming
from, and the constructor takes it from there. There is some meta-information,
however, at the beginning of each listing, and this is denoted by the
<B>packMarker</B>. If the <B>packMarker</B> isn’t there, it means the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -