发布一篇提代替码列表
在性能方面,在windows平台下,.net网页编程可能是占强项,要是把.net网页编程放在sun开发的操作系统上去运行呢?根本就运行不了,.net网页编程对其它操作系统的支持也很弱,性能也可能比不上java。关于本书每个完全的代码列表(不是代码段),人人无疑会注重到它们都用特别的正文暗号肇端与停止(//:和///:~)。之以是要包含这类标记信息,是为了能将代码从本书主动提取到兼容的源码文件中。在我的前一本书里,我计划了一个体系,可将测试过的代码文件主动兼并到书中。但关于这本书,我发明一种更烦琐的做法是一旦经由过程了最后的测试,就把代码粘贴到书中。并且因为很难第一次就编译经由过程,以是我在书的外部编纂代码。但怎样提取并测试代码呢?这个程序就是关头。假如你盘算办理一个笔墨处置的成绩,那末它也很有益用代价。该例也演示了String类的很多特征。
我起首将整本书都以ASCII文本格局保留成一个自力的文件。CodePackager程序有两种运转形式(在usageString有响应的形貌):假如利用-p标记,程序就会反省一个包括了ASCII文本(即本书的内容)的一个输出文件。它会遍历这个文件,依照正文暗号提掏出代码,并用位于第一行的文件名来决意创立文件利用甚么名字。除此之外,在必要将文件置进一个特别目次的时分,它还会反省package语句(依据由package语句指定的路径选择)。
但如许还不敷。程序还要对包(package)名举行跟踪,从而监督章内产生的变更。因为每章利用的一切包都以c02,c03,c04等等开端,用于标志它们所属的是哪一章(除那些以com开端的之外,它们在对分歧的章举行跟踪的时分会被疏忽)——只需每章的第一个代码列表包括了一个package,以是CodePackager程序能晓得每章产生的变更,并将后续的文件放到新的子目次里。
每一个文件提掏出来时,城市置进一个SourceCodeFile对象,随后再将谁人对象置进一个汇合(前面还会细致报告这个历程)。这些SourceCodeFile对象能够复杂地保留在文件中,那恰是本项目标第二个用处。假如间接挪用CodePackager,不增加-p标记,它就会将一个“打包”文件作为输出。谁人文件随后会被提取(开释)进进独自的文件。以是-p标记的意义就是提掏出来的文件已被“打包”(packed)进进这个单一的文件。
但为何还要云云贫苦地利用打包文件呢?这是因为分歧的盘算机平台用分歧的体例在文件里保留文本信息。个中最年夜的成绩是换行字符的暗示办法;固然,另有大概存在另外一些成绩。但是,Java有一种特别范例的IO数据流——DataOutputStream——它能够包管“不管数据来自何种呆板,只需利用一个DataInputStream收取这些数据,便可用本机准确的格局保留它们”。也就是说,Java卖力把持与分歧平台有关的一切细节,而这恰是Java最具魅力的一点。以是-p标记能将一切工具都保留到单一的文件里,并接纳通用的格局。用户可从Web下载这个文件和Java程序,然后对这个文件运转CodePackager,同时不指定-p标记,文件便会开释到体系中准确的场合(亦可指定另外一个子目次;不然就在以后目次创立子目次)。为确保不会留下与特定平台有关的格局,但凡必要形貌一个文件或路径的时分,我们就利用File对象。除此之外,另有一项出格的平安措施:在每一个子目次里都放进一个空文件;谁人文件的名字指出在谁人子目次里应找到几个文件。
上面是完全的代码,前面会对它举行具体的申明:
//:CodePackager.java
//"Packs"and"unpacks"thecodein"Thinking
//inJava"forcross-platformdistribution.
/*CommentedsoCodePackagerseesitandstarts
anewchapterdirectory,butsoyoudont
havetoworryaboutthedirectorywherethis
programlives:
packagec17;
*/
importjava.util.*;
importjava.io.*;
classPr{
staticvoiderror(Stringe){
System.err.println("ERROR:"+e);
System.exit(1);
}
}
classIO{
staticBufferedReaderdisOpen(Filef){
BufferedReaderin=null;
try{
in=newBufferedReader(
newFileReader(f));
}catch(IOExceptione){
Pr.error("couldnotopen"+f);
}
returnin;
}
staticBufferedReaderdisOpen(Stringfname){
returndisOpen(newFile(fname));
}
staticDataOutputStreamdosOpen(Filef){
DataOutputStreamin=null;
try{
in=newDataOutputStream(
newBufferedOutputStream(
newFileOutputStream(f)));
}catch(IOExceptione){
Pr.error("couldnotopen"+f);
}
returnin;
}
staticDataOutputStreamdosOpen(Stringfname){
returndosOpen(newFile(fname));
}
staticPrintWriterpsOpen(Filef){
PrintWriterin=null;
try{
in=newPrintWriter(
newBufferedWriter(
newFileWriter(f)));
}catch(IOExceptione){
Pr.error("couldnotopen"+f);
}
returnin;
}
staticPrintWriterpsOpen(Stringfname){
returnpsOpen(newFile(fname));
}
staticvoidclose(Writeros){
try{
os.close();
}catch(IOExceptione){
Pr.error("closing"+os);
}
}
staticvoidclose(DataOutputStreamos){
try{
os.close();
}catch(IOExceptione){
Pr.error("closing"+os);
}
}
staticvoidclose(Readeros){
try{
os.close();
}catch(IOExceptione){
Pr.error("closing"+os);
}
}
}
classSourceCodeFile{
publicstaticfinalString
startMarker="//:",//Startofsourcefile
endMarker="}///:~",//Endofsource
endMarker2="};///:~",//C++fileend
beginContinue="}///:Continued",
endContinue="///:Continuing",
packMarker="###",//Packedfileheadertag
eol=//Lineseparatoroncurrentsystem
System.getProperty("line.separator"),
filesep=//Systemsfilepathseparator
System.getProperty("file.separator");
publicstaticStringcopyright="";
static{
try{
BufferedReadercr=
newBufferedReader(
newFileReader("Copyright.txt"));
Stringcrin;
while((crin=cr.readLine())!=null)
copyright+=crin+"
";
cr.close();
}catch(Exceptione){
copyright="";
}
}
privateStringfilename,dirname,
contents=newString();
privatestaticStringchapter="c02";
//Thefilenameseparatorfromtheoldsystem:
publicstaticStringoldsep;
publicStringtoString(){
returndirname+filesep+filename;
}
//Constructorforparsingfromdocumentfile:
publicSourceCodeFile(StringfirstLine,
BufferedReaderin){
dirname=chapter;
//Skippastmarker:
filename=firstLine.substring(
startMarker.length()).trim();
//Findspacethatterminatesfilename:
if(filename.indexOf()!=-1)
filename=filename.substring(
0,filename.indexOf());
System.out.println("found:"+filename);
contents=firstLine+eol;
if(copyright.length()!=0)
contents+=copyright+eol;
Strings;
booleanfoundEndMarker=false;
try{
while((s=in.readLine())!=null){
if(s.startsWith(startMarker))
Pr.error("Noendoffilemarkerfor"+
filename);
//Forthisprogram,nospacesbefore
//the"package"keywordareallowed
//intheinputsourcecode:
elseif(s.startsWith("package")){
//Extractpackagename:
Stringpdir=s.substring(
s.indexOf()).trim();
pdir=pdir.substring(
0,pdir.indexOf(;)).trim();
//Capturethechapterfromthepackage
//ignoringthecomsubdirectories:
if(!pdir.startsWith("com")){
intfirstDot=pdir.indexOf(.);
if(firstDot!=-1)
chapter=
pdir.substring(0,firstDot);
else
chapter=pdir;
}
//Convertpackagenametopathname:
pdir=pdir.replace(
.,filesep.charAt(0));
System.out.println("package"+pdir);
dirname=pdir;
}
contents+=s+eol;
//Movepastcontinuations:
if(s.startsWith(beginContinue))
while((s=in.readLine())!=null)
if(s.startsWith(endContinue)){
contents+=s+eol;
break;
}
//Watchforendofcodelisting:
if(s.startsWith(endMarker)||
s.startsWith(endMarker2)){
foundEndMarker=true;
break;
}
}
if(!foundEndMarker)
Pr.error(
"EndmarkernotfoundbeforeEOF");
System.out.println("Chapter:"+chapter);
}catch(IOExceptione){
Pr.error("Errorreadingline");
}
}
//Forrecoveringfromapackedfile:
publicSourceCodeFile(BufferedReaderpFile){
try{
Strings=pFile.readLine();
if(s==null)return;
if(!s.startsWith(packMarker))
Pr.error("Cantfind"+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("listing:"+dirname
+filesep+filename);
while((s=pFile.readLine())!=null){
//Watchforendofcodelisting:
if(s.startsWith(endMarker)||
s.startsWith(endMarker2)){
contents+=s;
break;
}
contents+=s+eol;
}
}catch(IOExceptione){
System.err.println("Errorreadingline");
}
}
publicbooleanhasFile(){
returnfilename!=null;
}
publicStringdirectory(){returndirname;}
publicStringfilename(){returnfilename;}
publicStringcontents(){returncontents;}
//Towritetoapackedfile:
publicvoidwritePacked(DataOutputStreamout){
try{
out.writeBytes(
packMarker+dirname+"#"
+filename+eol);
out.writeBytes(contents);
}catch(IOExceptione){
Pr.error("writing"+dirname+
filesep+filename);
}
}
//Togeneratetheactualfile:
publicvoidwriteFile(Stringrootpath){
Filepath=newFile(rootpath,dirname);
path.mkdirs();
PrintWriterp=
IO.psOpen(newFile(path,filename));
p.print(contents);
IO.close(p);
}
}
classDirMap{
privateHashtablet=newHashtable();
privateStringrootpath;
DirMap(){
rootpath=System.getProperty("user.dir");
}
DirMap(StringalternateDir){
rootpath=alternateDir;
}
publicvoidadd(SourceCodeFilef){
Stringpath=f.directory();
if(!t.containsKey(path))
t.put(path,newVector());
((Vector)t.get(path)).addElement(f);
}
publicvoidwritePackedFile(Stringfname){
DataOutputStreampacked=IO.dosOpen(fname);
try{
packed.writeBytes("###OldSeparator:"+
SourceCodeFile.filesep+"###
");
}catch(IOExceptione){
Pr.error("Writingseparatorto"+fname);
}
Enumeratione=t.keys();
while(e.hasMoreElements()){
Stringdir=(String)e.nextElement();
System.out.println(
"Writingdirectory"+dir);
Vectorv=(Vector)t.get(dir);
for(inti=0;i<v.size();i++){
SourceCodeFilef=
(SourceCodeFile)v.elementAt(i);
f.writePacked(packed);
}
}
IO.close(packed);
}
//Writeallthefilesintheirdirectories:
publicvoidwrite(){
Enumeratione=t.keys();
while(e.hasMoreElements()){
Stringdir=(String)e.nextElement();
Vectorv=(Vector)t.get(dir);
for(inti=0;i<v.size();i++){
SourceCodeFilef=
(SourceCodeFile)v.elementAt(i);
f.writeFile(rootpath);
}
//Addfileindicatingfilequantity
//writtentothisdirectoryasacheck:
IO.close(IO.dosOpen(
newFile(newFile(rootpath,dir),
Integer.toString(v.size())+".files")));
}
}
}
publicclassCodePackager{
privatestaticfinalStringusageString=
"usage:javaCodePackagerpackedFileName"+
"
Extractssourcecodefilesfrompacked
"+
"versionofTjava.docsourcesinto"+
"directoriesoffcurrentdirectory
"+
"javaCodePackagerpackedFileNamenewDir
"+
"ExtractsintodirectoriesoffnewDir
"+
"javaCodePackager-psource.txtpackedFile"+
"
Createspackedversionofsourcefiles"+
"
fromtextversionofTjava.doc";
privatestaticvoidusage(){
System.err.println(usageString);
System.exit(1);
}
publicstaticvoidmain(String[]args){
if(args.length==0)usage();
if(args.equals("-p")){
if(args.length!=3)
usage();
createPackedFile(args);
}
else{
if(args.length>2)
usage();
extractPackedFile(args);
}
}
privatestaticStringcurrentLine;
privatestaticBufferedReaderin;
privatestaticDirMapdm;
privatestaticvoid
createPackedFile(String[]args){
dm=newDirMap();
in=IO.disOpen(args);
try{
while((currentLine=in.readLine())
!=null){
if(currentLine.startsWith(
SourceCodeFile.startMarker)){
dm.add(newSourceCodeFile(
currentLine,in));
}
elseif(currentLine.startsWith(
SourceCodeFile.endMarker))
Pr.error("filehasnostartmarker");
//Elseignoretheinputline
}
}catch(IOExceptione){
Pr.error("Errorreading"+args);
}
IO.close(in);
dm.writePackedFile(args);
}
privatestaticvoid
extractPackedFile(String[]args){
if(args.length==2)//Alternatedirectory
dm=newDirMap(args);
else//Currentdirectory
dm=newDirMap();
in=IO.disOpen(args);
Strings=null;
try{
s=in.readLine();
}catch(IOExceptione){
Pr.error("Cannotreadfrom"+in);
}
//Capturetheseparatorusedinthesystem
//thatpackedthefile:
if(s.indexOf("###OldSeparator:")!=-1){
Stringoldsep=s.substring(
"###OldSeparator:".length());
oldsep=oldsep.substring(
0,oldsep.indexOf(#));
SourceCodeFile.oldsep=oldsep;
}
SourceCodeFilesf=newSourceCodeFile(in);
while(sf.hasFile()){
dm.add(sf);
sf=newSourceCodeFile(in);
}
dm.write();
}
}///:~
我们注重到package语句已作为正文标记出来了。因为这是本章的第一个程序,以是package语句是必须的,用它告知CodePackager已更换到另外一章。可是把它放进包里却会成为一个成绩。当我们创立一个包的时分,必要将了局程序统一个特定的目次布局接洽在一同,这一做法对本书的年夜多半例子都是合用的。但在这里,CodePackager程序必需在一个公用的目次里编译和运转,以是package语句作为正文标志进来。但对CodePackager来讲,它“看起来”仍然象一个一般的package语句,由于程序还不是出格庞大,不克不及侦察到多行正文(没有需要做得这么庞大,这里只需求便利就行)。
头两个类是“撑持/工具”类,感化是使程序残剩的部分在编写时加倍联贯,也更便于浏览。第一个是Pr,它相似ANSIC的perror库,二者都能打印出一条毛病提醒动静(但同时也会加入程序)。第二个类将文件的创立历程封装在内,这个历程已在第10章先容过了;人人已晓得,如许做很快就会变得十分包袱和贫苦。为办理这个成绩,第10章供应的计划努力于新类的创立,但这儿的“静态”办法已利用过了。在那些办法中,一般的背例会被捕捉,并响应地举行处置。这些办法使残剩的代码显得加倍清新,更容易浏览。
匡助办理成绩的第一个类是SourceCodeFile(源码文件),它代表本书一个源码文件包括的一切信息(内容、文件名和目次)。它同时还包括了一系列String常数,分离代表一个文件的入手下手与停止;在打包文件内利用的一个标志;以后体系的换行符;文件路径分开符(注重要用System.getProperty()侦察当地版本是甚么);和一年夜段版权声明,它是从上面这个Copyright.txt文件里提掏出来的:
//////////////////////////////////////////////////
//Copyright(c)BruceEckel,1998
//Sourcecodefilefromthebook"ThinkinginJava"
//AllrightsreservedEXCEPTasallowedbythe
//followingstatements:Youmayfreelyusethisfile
//foryourownwork(personalorcommercial),
//includingmodificationsanddistributionin
//executableformonly.Permissionisgrantedtouse
//thisfileinclassroomsituations,includingits
//useinpresentationmaterials,aslongasthebook
//"ThinkinginJava"iscitedasthesource.
//Exceptinclassroomsituations,youmaynotcopy
//anddistributethiscode;instead,thesole
//distributionpointishttp://www.BruceEckel.com
//(andofficialmirrorsites)whereitis
//freelyavailable.Youmaynotremovethis
//copyrightandnotice.Youmaynotdistribute
//modifiedversionsofthesourcecodeinthis
//package.Youmaynotusethisfileinprinted
//mediawithouttheexpresspermissionofthe
//author.BruceEckelmakesnorepresentationabout
//thesuitabilityofthissoftwareforanypurpose.
//Itisprovided"asis"withoutexpressorimplied
//warrantyofanykind,includinganyimplied
//warrantyofmerchantability,fitnessfora
//particularpurposeornon-infringement.Theentire
//riskastothequalityandperformanceofthe
//softwareiswithyou.BruceEckelandthe
//publishershallnotbeliableforanydamages
//sufferedbyyouoranythirdpartyasaresultof
//usingordistributingsoftware.Innoeventwill
//BruceEckelorthepublisherbeliableforany
//lostrevenue,profit,ordata,orfordirect,
//indirect,special,consequential,incidental,or
//punitivedamages,howevercausedandregardlessof
//thetheoryofliability,arisingoutoftheuseof
//orinabilitytousesoftware,evenifBruceEckel
//andthepublisherhavebeenadvisedofthe
//possibilityofsuchdamages.Shouldthesoftware
//provedefective,youassumethecostofall
//necessaryservicing,repair,orcorrection.Ifyou
//thinkyouvefoundanerror,pleaseemailall
//modifiedfileswithclearlycommentedchangesto:
//Bruce@EckelObjects.com.(pleaseusethesame
//addressfornon-codeerrorsfoundinthebook).
//////////////////////////////////////////////////
从一个打包文件中提取文件时,现在所用体系的文件分开符也会标注出来,以便用当地体系合用的标记交换它。
以后章的子目次保留在chapter字段中,它初始化成c02(人人可注重一下第2章的列表恰好没有包括一个打包语句)。只要在以后文件里发明一个package(打包)语句时,chapter字段才会产生改动。
1.构建一个打包文件
第一个构建器用于从本书的ASCII文本版里提掏出一个文件。收回挪用的代码(在列内外较深的中央)会读进并反省每行,直到找到与一个列表的开首符合的为止。在这个时分,它就会新建一个SourceCodeFile对象,将第一行的内容(已由挪用代码读进了)传送给它,同时还要传送BufferedReader对象,以便在这个缓冲区中提取源码列表残剩的内容。
从这时候起,人人会发明String办法被频仍使用。为提掏出文件名,需挪用substring()的过载版本,令其从一个肇端偏移入手下手,一向读到字串的开端,从而构成一个“子串”。为算出这个肇端索引,先要用length()得出startMarker的总长,再用trim()删除字串头尾过剩的空格。第一行在文件名后也大概有一些字符;它们是用indexOf()侦测出来的。若没有发明找到我们想寻觅的字符,就前往-1;若找到那些字符,就前往它们第一次呈现的地位。注重这也是indexOf()的一个过载版本,接纳一个字串作为参数,而非一个字符。
剖析出并保留好文件名后,第一行会被置进字串contents中(该字串用于保留源码清单的完全注释)。随后,将残剩的代码行读进,并兼并进进contents字串。固然事变并没有设想的那末复杂,由于特定的情形需加以出格的把持。一种情形是毛病反省:若间接碰到一个startMarker(肇端标志),标明以后操纵的这个代码列表没有设置一个停止标志。这属于一个堕落前提,必要加入程序。
另外一种特别情形与package关头字有关。只管Java是一种自在情势的言语,但这个程序请求package关头字必需位于行首。若发明package关头字,就经由过程反省位于开首的空格和位于开端的分号,从而提掏出包名(注重亦可一次独自的操纵完成,办法是利用过载的substring(),令其同时反省肇端和停止索引地位)。随后,将包名中的点号交换成特定的文件分开符——固然,这里要假定文件分开符唯一一个字符的长度。只管这个假定大概对今朝的一切体系都是合用的,但一旦碰到成绩,必定不要忘了反省一下这里。
默许操纵是将每行都毗连到contents里,同时另有换行字符,直到碰到一个endMarker(停止标志)为止。该标志指出构建器应该中断了。若在endMarker之前碰到了文件开头,就以为存在一个毛病。
2.从打包文件中提取
第二个构建器用于将源码文件从打包文件中恢复(提取)出来。在这儿,作为挪用者的办法不用忧虑会跳过一些两头文本。打包文件包括了一切源码文件,它们互相间严密地靠在一同。必要传送给该构建器的仅仅是一个BufferedReader,它代表着“信息源”。构建器会从中提掏出本人必要的信息。但在每一个代码列表入手下手的中央另有一些设置信息,它们的身份是用packMarker(打包标志)指出的。若packMarker不存在,意味着挪用者试图用毛病的办法来利用这个构建器。
一旦发明packMarker,就会将其剥离出来,并提掏出目次名(用一个#开头)和文件名(直到行末)。不论在哪一种情形下,旧分开符城市被交换本钱地合用的一个分开符,这是用Stringreplace()办法完成的。老的分开符被置于打包文件的开首,在代码列表稍靠后的一部分便可看到是怎样把它提掏出来的。
构建器剩下的部分就十分复杂了。它读进每行,把它兼并到contents里,直到碰见endMarker为止。
3.程序列表的存取
接上去的一系列办法是复杂的会见器:directory()、filename()(注重办法大概与字段有不异的拼写和巨细写情势)和contents()。而hasFile()用于指出这个对象是不是包括了一个文件(很快就会晓得为何必要这个)。
最初三个办法努力于将这个代码列表写进一个文件——要末经由过程writePacked()写进一个打包文件,要末经由过程writeFile()写进一个Java源码文件。writePacked()必要的独一工具就是DataOutputStream,它是在其余中央翻开的,代表着筹办写进的文件。它先把头信息置进第一行,再挪用writeBytes()将contents(内容)写成一种“通用”格局。
筹办写Java源码文件时,必需先把文件建好。这是用IO.psOpen()完成的。我们必要向它传送一个File对象,个中不但包括了文件名,也包括了路径信息。但如今的成绩是:这个路径实践存在吗?用户大概决意将一切源码目次都置进一个完整分歧的子目次,谁人目次多是尚不存在的。以是在正式写每一个文件之前,都要挪用File.mkdirs()办法,建好我们想向个中写进文件的目次路径。它可一次性建好全部路径。
4.整套列表的包涵
以子目次的情势构造代码列表长短常便利的,只管这请求先在内存中建好整套列表。之以是要如许做,另有另外一个很有压服力的缘故原由:为了构建更“安康”的体系。也就是说,在创立代码列表的每一个子目次时,城市到场一个分外的文件,它的名字包括了谁人目次内应有的文件数量。
DirMap类可匡助我们完成这一效果,并无效地演示了一个“多重映照”的概述。这是经由过程一个散列表(Hashtable)完成的,它的“键”是筹办创立的子目次,而“值”是包括了谁人特定目次中的SourceCodeFile对象的Vector对象。以是,我们在这儿并非将一个“键”映照(或对应)到一个值,而是经由过程对应的Vector,将一个键“多重映照”到一系列值。只管这听起来仿佛很庞大,但详细完成时倒是十分复杂和间接的。人人能够看到,DirMap类的年夜多半代码都与向文件中的写进有关,而非与“多重映照”有关。与它有关的代码仅少少数罢了。
可经由过程两种体例创建一个DirMap(目次映照或对应)干系:默许构建器假定我们但愿目次从以后地位向下睁开,而另外一个构建器让我们为肇端目次指定一个备用的“相对”路径。
add()办法是一个接纳的举动对照麋集的场合。起首将directory()从我们想增加的SourceCodeFile里提掏出来,然后反省散列表(Hashtable),看看个中是不是已包括了谁人键。假如没有,就向散列表到场一个新的Vector,并将它同谁人键联系关系到一同。到这时候,不论接纳的是甚么路子,Vector都已就位了,能够将它提掏出来,以便增加SourceCodeFile。因为Vector可象如许同散列表便利地兼并到一同,以是我们从两方面都能感到得十分便利。
写一个打包文件时,需翻开一个筹办写进的文件(看成DataOutputStream翻开,使数据具有“通用”性),并在第一行写进与老的分开符有关的头信息。接着发生对Hashtable键的一个Enumeration(列举),并遍历个中,选择每个目次,并获得与谁人目次有关的Vector,使谁人Vector中的每一个SourceCodeFile都能写进打包文件中。
用write()将Java源码文件写进它们对应的目次时,接纳的办法几近与writePackedFile()完整分歧,由于两个办法都只需复杂挪用SourceCodeFile中得当的办法。但在这里,根路径会传送给SourceCodeFile.writeFile()。一切文件都写好后,名字中指定了已写文件数目的谁人附加文件也会被写进。
5.主程序
后面先容的那些类都要在CodePackager顶用到。人人起首看到的是用法字串。一旦终极用户不准确地挪用了程序,就会打印出先容准确用法的这个字串。挪用这个字串的是usage()办法,同时还要加入程序。main()独一的义务就是判别我们但愿创立一个打包文件,仍是但愿从一个打包文件中提取甚么工具。随后,它卖力包管利用的是准确的参数,并挪用得当的办法。
创立一个打包文件时,它默许位于以后目次,以是我们用默许构建器创立DirMap。翻开文件后,个中的每行城市读进,并反省是不是切合特别的前提:
(1)若行首是一个用于源码列表的肇端标志,就新建一个SourceCodeFile对象。构建器会读进源码列表剩下的一切内容。了局发生的句柄将间接到场DirMap。
(2)若行首是一个用于源码列表的停止标志,标明某个中央呈现毛病,由于停止标志应该只能由SourceCodeFile构建器发明。
提取/开释一个打包文件时,提掏出来的内容可进进以后目次,亦可进进另外一个备用目次。以是必要响应地创立DirMap对象。翻开文件,并将第一行读进。老的文件路径分开符信息将从这一行中提掏出来。随后依据输出来创立第一个SourceCodeFile对象,它会到场DirMap。只需包括了一个文件,新的SourceCodeFile对象就会创立并到场(创立的最初一个用光输出内容后,会复杂地前往,然后hasFile()会前往一个毛病)。
用java开发web只要两本书:一本是关于java基础的,一本是关于jsp、servlet的就可以了。开发周期长,我就来讲句题外话,现在有很多思想都是通过java来展现。 任职于太阳微系统的詹姆斯·高斯林等人于1990年代初开发Java语言的雏形,最初被命名为Oak,目标设置在家用电器等小型系统的程序语言 Java是一种计算机编程语言,拥有跨平台、面向对java Sun公司看见Oak在互联网上应用的前景,于是改造了Oak,于1995年5月以Java的名称正式发布。Java伴随着互联网的迅猛发展而发展,逐渐成为重要的网络编程语言。 设计模式是高级程序员真正掌握面向对象核心思想的必修课。设计模式并不是一种具体"技术",它讲述的是思想,它不仅仅展示了接口或抽象类在实际案例中的灵活应用和智慧 J2SE开发桌面应用软件比起 VC,VB,DEPHI这些传统开发语言来说,优势好象并不明显。J2ME对于初学者来说,好象又有点深奥,而且一般开发者很难有开发环境。 接着就是EJB了,EJB就是Enterprise JavaBean, 看名字好象它是Javabean,可是它和Javabean还是有区别的。它是一个体系结构,你可以搭建更安全、更稳定的企业应用。它的大量代码已由中间件(也就是我们常听到的 Weblogic,Websphere这些J2EE服务器)完成了,所以我们要做的程序代码量很少,大部分工作都在设计和配置中间件上。 学Java必读的两个开源程序就是Jive和Pet Store.。 Jive是国外一个非常著名的BBS程序,完全开放源码。论坛的设计采用了很多先进的技术,如Cache、用户认证、Filter、XML等,而且论坛完全屏蔽了对数据库的访问,可以很轻易的在不同数据库中移植。论坛还有方便的安装和管理程序,这是我们平时编程时容易忽略的一部份(中国程序员一般只注重编程的技术含量,却完全不考虑用户的感受,这就是我们与国外软件的差距所在)。 是一种语言,用以产生「小应用程序(Applet(s)) 你一定会高兴地说,哈哈,原来成为Java高手就这么简单啊!记得Tomjava也曾碰到过一个项目经理,号称Java很简单,只要三个月就可以学会。 是一种使用者不需花费很多时间学习的语言 是一种突破用户端机器环境和CPU 关于设计模式的资料,还是向大家推荐banq的网站 http://www.jdon.com/,他把GOF的23种模式以通俗易懂的方式诠释出来,纯Java描述,真是经典中的经典。 你现在最缺的是实际的工作经验,而不是书本上那些凭空想出来的程序。 《JAVA语言程序设计》或《JAVA从入门到精通》这两本书开始学,等你编程有感觉的时候也可以回看一下。《JAVA读书笔记》这本书,因为讲的代码很多,也很容易看懂,涉及到面也到位。是你学习技术巩固的好书,学完后就看看《JAVA编程思想》这本书,找找一个自己写的代码跟书上的代码有什么不一样。 另外编写和运行Java程序需要JDK(包括JRE),在sun的官方网站上有下载,thinking in java第三版用的JDK版本是1.4,现在流行的版本1.5(sun称作J2SE 5.0,汗),不过听说Bruce的TIJ第四版国外已经出来了,是专门为J2SE 5.0而写的。 接着就是EJB了,EJB就是Enterprise JavaBean, 看名字好象它是Javabean,可是它和Javabean还是有区别的。它是一个体系结构,你可以搭建更安全、更稳定的企业应用。它的大量代码已由中间件(也就是我们常听到的 Weblogic,Websphere这些J2EE服务器)完成了,所以我们要做的程序代码量很少,大部分工作都在设计和配置中间件上。 设计模式是高级程序员真正掌握面向对象核心思想的必修课。设计模式并不是一种具体"技术",它讲述的是思想,它不仅仅展示了接口或抽象类在实际案例中的灵活应用和智慧 当然你也可以参加一些开源项目,一方面可以提高自己,另一方面也是为中国软件事业做贡献嘛!开发者在互联网上用CVS合作开发,用QQ,MSN,E-mail讨论联系,天南海北的程序员分散在各地却同时开发同一个软件,是不是很有意思呢? 不过,每次的执行编译后的字节码需要消耗一定的时间,这同时也在一定程度上降低了 Java 程序的运行效率。
页:
[1]