友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!
Java编程思想第4版[中文版](PDF格式)-第146部分
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部! 如果本书没有阅读完,想下次继续接着阅读,可使用上方 "收藏到我的浏览器" 功能 和 "加入书签" 功能!
dirname = pdir;
}
contents += s + eol;
// Move past continuations:
if(s。startsWith(beginContinue))
while((s = in。readLine()) != null)
if(s。startsWith(endContinue)) {
contents += s + eol;
break;
}
// Watch for end of code listing:
if(s。startsWith(endMarker) ||
s。startsWith(endMarker2)) {
foundEndMarker = true;
break;
}
}
if(!foundEndMarker)
Pr。error(
〃End marker not found before EOF〃);
System。out。println(〃Chapter: 〃 + chapter);
} catch(IOException e) {
Pr。error(〃Error reading line〃);
}
}
// For recovering from a packed file:
public SourceCodeFile(BufferedReader pFile) {
try {
String s = pFile。readLine();
if(s == null) return;
if(!s。startsWith(packMarker))
Pr。error(〃Can't find 〃 + packMarker
+ 〃 in 〃 + s);
s = s。substring(
packMarker。length())。trim();
dirname = s。substring(0; s。indexOf('#'));
filename = s。substring(s。indexOf('#') + 1);
dirname = dirname。replace(
oldsep。charAt(0); filesep。charAt(0));
filename = filename。replace(
oldsep。charAt(0); filesep。charAt(0));
System。out。println(〃l isting: 〃 + dirname
+ filesep + filename);
while((s = pFile。readLine()) != null) {
// Watch for end of code listing:
if(s。startsWith(endMarker) ||
s。startsWith(endMarker2)) {
contents += s;
626
…………………………………………………………Page 628……………………………………………………………
break;
}
contents += s + eol;
}
} catch(IOException e) {
System。err。println(〃Error reading line〃);
}
}
public boolean hasFile() {
return filename != null;
}
public String directory() { return dirname; }
public String filename() { return filename; }
public String contents() { return contents; }
// To write to a packed file:
public void writePacked(DataOutputStream out) {
try {
out。writeBytes(
packMarker + dirname + 〃#〃
+ filename + eol);
out。writeBytes(contents);
} catch(IOException e) {
Pr。error(〃writing 〃 + dirname +
filesep + filename);
}
}
// To generate the actual file:
public void writeFile(String rootpath) {
File path = new File(rootpath; dirname);
path。mkdirs();
PrintWriter p =
IO。psOpen(new File(path; filename));
p。print(contents);
IO。close(p);
}
}
class DirMap {
private Hashtable t = new Hashtable();
private String rootpath;
DirMap() {
rootpath = System。getProperty(〃user。dir〃);
}
DirMap(String alternateDir) {
rootpath = alternateDir;
}
public void add(SourceCodeFile f){
String path = f。directory();
if(!t。containsKey(path))
t。put(path; new Vector());
((Vector)t。get(path))。addElement(f);
}
627
…………………………………………………………Page 629……………………………………………………………
public void writePackedFile(String fname) {
DataOutputStream packed = IO。dosOpen(fname);
try {
packed。writeBytes(〃###Old Separator:〃 +
SourceCodeFile。filesep + 〃###n〃);
} catch(IOException e) {
Pr。error(〃Writing separator to 〃 + fname);
}
Enumeration e = t。keys();
while(e。hasMoreElements()) {
String dir = (String)e。nextElement();
System。out。println(
〃Writing directory 〃 + dir);
Vector v = (Vector)t。get(dir);
for(int i = 0; i 《 v。size(); i++) {
SourceCodeFile f =
(SourceCodeFile)v。elementAt(i);
f。writePacked(packed);
}
}
IO。close(packed);
}
// Write all the files in their directories:
public void write() {
Enumeration e = t。keys();
while(e。hasMoreElements()) {
String dir = (String)e。nextElement();
Vector v = (Vector)t。get(dir);
for(int i = 0; i 《 v。size(); i++) {
SourceCodeFile f =
(SourceCodeFile)v。elementAt(i);
f。writeFile(rootpath);
}
// Add file indicating file quantity
// written to this directory as a check:
IO。close(IO。dosOpen(
new File(new File(rootpath; dir);
Integer。toString(v。size())+〃。files〃)));
}
}
}
public class CodePackager {
private static final String usageString =
〃usage: java CodePackager packedFileName〃 +
〃nExtracts source code files from packed n〃 +
〃version of Tjava。doc sources into 〃 +
〃directories off current directory n〃 +
〃java CodePackager packedFileName newDirn〃 +
〃Extracts into directories off newDirn〃 +
〃java CodePackager …p source。txt packedFile〃 +
〃nCreates packed version of source files〃 +
628
…………………………………………………………Page 630……………………………………………………………
〃nfrom text version of Tjava。doc〃;
private static void usage() {
System。err。println(usageString);
System。exit(1);
}
public static void main(String'' args) {
if(args。length == 0) usage();
if(args'0'。equals(〃…p〃)) {
if(args。length != 3)
usage();
createPackedFile(args);
}
else {
if(args。length 》 2)
usage();
extractPackedFile(args);
}
}
private static String currentLine;
private static BufferedReader in;
private static DirMap dm;
private static void
createPackedFile(String'' args) {
dm = new DirMap();
in = IO。disOpen(args'1');
try {
while((currentLine = in。readLine())
!= null) {
if(currentLine。startsWith(
SourceCodeFile。startMarker)) {
dm。add(new SourceCodeFile(
currentLine; in));
}
else if(currentLine。startsWith(
SourceCodeFile。endMarker))
Pr。error(〃file has no start marker〃);
// Else ignore the input line
}
} catch(IOException e) {
Pr。error(〃Error reading 〃 + args'1');
}
IO。close(in);
dm。writePackedFile(args'2');
}
private static void
extractPackedFile(String'' args) {
if(args。length == 2) // Alternate directory
dm = new DirMap(args'1');
else // Current directory
dm = new DirMap();
in = IO。disOpen(args'0');
String s = null;
629
…………………………………………………………Page 631……………………………………………………………
try {
s = in。readLine();
} catch(IOException e) {
Pr。error(〃Cannot read from 〃 + in);
}
// Capture the separator used in the system
// that packed the file:
if(s。indexOf(〃###Old Separator:〃) != …1 ) {
String oldsep = s。substring(
〃###Old Separator:〃。length());
oldsep = oldsep。substring(
0; oldsep。 indexOf('#'));
SourceCodeFile。oldsep = oldsep;
}
SourceCodeFile sf = new SourceCodeFile(in);
while(sf。hasFile()) {
dm。add(sf);
sf = new SourceCodeFile(in);
}
dm。write();
}
} ///:~
我们注意到 package 语句已经作为注释标志出来了。由于这是本章的第一个程序,所以package 语句是必需
的,用它告诉CodePackager 已改换到另一章。但是把它放入包里却会成为一个问题。当我们创建一个包的时
候,需要将结果程序同一个特定的目录结构联系在一起,这一做法对本书的大多数例子都是适用的。但在这
里,CodePackager 程序必须在一个专用的目录里编译和运行,所以 package 语句作为注释标记出去。但对
CodePackager 来说,它“看起来”依然象一个普通的package 语句,因为程序还不是特别复杂,不能侦查到
多行注释(没有必要做得这么复杂,这里只要求方便就行)。
头两个类是“支持/工具”类,作用是使程序剩余的部分在编写时更加连贯,也更便于阅读。第一个是Pr,
它类似ANSI C 的perror 库,两者都能打印出一条错误提示消息(但同时也会退出程序)。第二个类将文件
的创建过程封装在内,这个过程已在第10章介绍过了;大家已经知道,这样做很快就会变得非常累赘和麻
烦。为解决这个问题,第 10 章提供的方案致力于新类的创建,但这儿的“静态”方法已经使用过了。在那些
方法中,正常的违例会被捕获,并相应地进行处理。这些方法使剩余的代码显得更加清爽,更易阅读。
帮助解决问题的第一个类是SourceCodeFile (源码文件),它代表本书一个源码文件包含的所有信息(内
容、文件名以及目录)。它同时还包含了一系列String 常数,分别代表一个文件的开始与结束;在打包文件
内使用的一个标记;当前系统的换行符;文件路径分隔符(注意要用System。getProperty()侦查本地版本是
什么);以及一大段版权声明,它是从下面这个Copyright。txt 文件里提取出来的:
//////////////////////////////////////////////////
// Copyright (c) Bruce Eckel; 1998
// Source code file from the book 〃Thinking in Java〃
// All rights reserved EXCEPT as allowed by the
// following statements: You may freely use this file
// for your own work (personal or mercial);
// including modifications and distribution in
// executable form only。 Permission is granted to use
// this file in classroom situations; including its
// use in presentation materials; as long as the book
// 〃Thinking in Java〃 is cited as the source。
// Except in classroom situations; you may not copy
// and distribute this code; instead; the sole
630
…………………………………………………………Page 632……………………………………………………………
// distribution point is http://BruceEckel。
// (and official mirror sites) where it is
// freely available。 You may not remove this
// copyright and notice。 You may not distribute
// modified versions of the source code in this
// package。 You may not use this file in printed
// media without the express permission of the
// author。 Bruce Eckel makes no representation about
// the suitability of this software for any purpose。
// It is provided 〃as is〃 without express or implied
// warranty of any kind; including any implied
// warranty of merchantability; fitness for a
// particular purpose or non…infringement。 The entire
// risk as to th
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!