版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
Java的輸入/輸出流7.1Java語(yǔ)言I/O的類(lèi)層次Java輸入/輸出流封裝在包java.io中,其常用的層次結(jié)構(gòu)如圖7.1、7.2所示。除了圖中給出的類(lèi)外,實(shí)際使用中,我們還會(huì)碰到File類(lèi),它用來(lái)描述某個(gè)檔的資訊。輸入/輸出類(lèi)中還有幾個(gè)比較重要的介面,例如:DataInput、DataOutput、FileNameFilter。後面我們會(huì)作詳細(xì)的介紹。圖7.1圖7.2Java的流方法從結(jié)構(gòu)上可以分為三大類(lèi):位元組流、數(shù)據(jù)流和列印流。位元組輸入/輸出流操作對(duì)象為位元組(byte);數(shù)據(jù)流的數(shù)據(jù)比較多,包含所有基本類(lèi)型的二進(jìn)位數(shù)據(jù);列印流是機(jī)器能夠識(shí)別的字元形式(包括ASCII碼和Unicode碼)。7.2Java中文件的操作
編寫(xiě)程式免不了要經(jīng)常與檔打交道,檔的輸入/輸出需要用到圖7.1中所列出的類(lèi)FileInputStream、FileOutputStream及RandomAccessFile類(lèi)。前兩個(gè)類(lèi)針對(duì)於順序檔的存取,後一個(gè)類(lèi)用於隨機(jī)檔的讀取。後面我們會(huì)有詳細(xì)的介紹。7.2.1檔與目錄的描述類(lèi)——FileFile類(lèi)並不用來(lái)進(jìn)行檔的讀/寫(xiě)操作,它用來(lái)描述檔對(duì)象的屬性,既可以表示檔,也可以表示目錄。使用它提供的方法,我們可以得到所指對(duì)象的描述資訊,包括名稱(chēng)、存在否、讀/寫(xiě)許可權(quán)、路徑等等。需要注意的是,當(dāng)我們?cè)赪indows環(huán)境使用路徑時(shí),其分隔符號(hào)不能是單一的“\”符號(hào),因?yàn)榕cC/C++相同,符號(hào)“\”已經(jīng)被轉(zhuǎn)意了。例如:c:\jbuilder3\java\bin路徑是非法的,系統(tǒng)不會(huì)識(shí)別,正確的應(yīng)該為c:\\jbilder3\\java\\bin下麵我們通過(guò)表7.1給出File類(lèi)的一些方法及說(shuō)明。表7.1File類(lèi)的方法及變數(shù)方法及變數(shù)名功能描述publicFile(Filedir,Stringname)由指定的目錄、名字創(chuàng)建該對(duì)象publicFile(Stringpath,Stringname)由指定的路徑、名字創(chuàng)建該對(duì)象publicFile(Stringpath)由指定路徑創(chuàng)建該對(duì)象publicstaticfinalStringpathSeparator返回系統(tǒng)的路徑分隔符號(hào)publicbooleancanRead()如果檔可讀為真publicbooleancanWrite()如果檔可寫(xiě)為真publicbooleandelete()刪除檔publicbooleanequals(Objectobj)檔比較,如是同一個(gè)檔則為真publicbooleanexists()指定的檔存在返回真publicStringgetAbsolutePath()得到檔的絕對(duì)路徑publicStringgetName()得到檔案名publicStringgetParent()得到父目錄的名字publicStringgetPath()返回路徑publicinthashCode()返回一個(gè)哈希碼publicnativebooleanisAbsolute()如果是絕對(duì)路徑返回真publicbooleanisDirectory()如果是目錄則返回真publicbooleanisFile()如果是檔則返回真publiclonglastModified()返回最近一次修改時(shí)間publiclonglength()返回檔長(zhǎng)度publicString[]list(FilenameFilterfilter)返回指定格式的目錄中的檔案名publicString[]list()返回當(dāng)前目錄中的所有檔案名publicbooleanmkdir()創(chuàng)建目錄,成功返回真publicbooleanmkdirs()創(chuàng)建路徑中所有目錄,成功則返回真publicstaticfinalcharpathSeparatorChar返回路徑分隔符號(hào)publicbooleanrenameTo(Filedest)檔更名,成功返回真publicstaticfinalcharseparatorChar返回檔分隔符號(hào)publicStringtoString()返回對(duì)象的字串表示
下麵我們給出幾個(gè)File類(lèi)的應(yīng)用實(shí)例。通過(guò)例題的使用,希望讀者對(duì)File類(lèi)有更清楚的認(rèn)識(shí)。例7.1importjava.io.*;publicclassMyClass1{
publicstaticvoidmain(Stringargs[]){
Filef=newFile("c:\\jbuilder3\\myprojects\\untitled5\\MyClass1.java");if(!f.exists())Transcript.println("FileMyClass1.javadoesn'texist!");else{Transcript.println("Thisfilecanread"+f.canRead());Transcript.println("lastmodified"+f.lastModified());Transcript.println("Parentis"+f.getParent());Transcript.println("Filelengthis"+f.length());}}publicMyClass1(){}}
該程式的運(yùn)行結(jié)果如圖7.3所示。此程式中,我們?yōu)榱苏f(shuō)明路徑分隔符號(hào)的使用方法,實(shí)例化檔對(duì)象的時(shí)候給出了全路徑,其實(shí)由於我們已經(jīng)在Java系統(tǒng)中設(shè)置好了源路徑,只要給出檔案名就行了。表7.1中,list方法用於列出一個(gè)目錄中所有的檔或與某個(gè)模式相匹配的檔。下麵我們給出兩個(gè)例子來(lái)討論帶參數(shù)或不帶參數(shù)的list方法的使用。圖7.3例7.2importjava.io.*;publicclassMyClass2{publicstaticvoidmain(Stringargs[]){Filef1=newFile("c:\\jbuilder3\\myprojects");if(!f1.isDirectory())Transcript.println("Error:"+f1+"isn'tadirectory!");else{StringdirList[]=f1.list();for(inti=0;i<dirList.length;i++)Transcript.println(dirList[i]);}
}}
publicMyClass2(){}}
在該例中,我們並沒(méi)有在調(diào)用File類(lèi)的list方法中傳遞參數(shù),這樣,處在目錄c:\\jbuilder3\\myprojects下的所有檔及目錄將均被輸出,結(jié)果如圖7.4所示。
圖7.3圖7.4
程式設(shè)計(jì)中,往往會(huì)碰到根據(jù)某一匹配模式來(lái)查找目錄下的檔的問(wèn)題,這時(shí)就需使用File類(lèi)帶參數(shù)的list方法,即
publicString[]list(FilenameFilterfilter)
其中,參數(shù)FilenameFilter是一個(gè)介面,只有一個(gè)方法的定義:
booleanaccept(Filedir,Stringname);
對(duì)於指定目錄下的檔,我們可以調(diào)用該方法確定某個(gè)檔是否包含於其中。比如上例中,我們查找以“un”打頭的檔或目錄,程式如下:例7.3importjava.io.*;publicclassMyClass3implementsFilenameFilter{Filef;publicstaticvoidmain(Stringargs[]){Filef1=newFile("c:\\jbuilder3\\myprojects");if(!f1.isDirectory())Transcript.println("Error:"+f1+"isn'tadirectory!");else{MyClass3m=newMyClass3(f1);StringdirList[]=f1.list(m);for(inti=0;i<dirList.length;i++)Transcript.println(dirList[i]);}}publicMyClass3(Filef){this.f=f;}publicbooleanaccept(Filedir,Stringname){returnname.startsWith("un");}}7.2.2檔I/O處理
1.Byte流(位元組流)檔的讀取該類(lèi)的結(jié)構(gòu)如圖7.1所示,我們主要用其中的FileOutputStream和FileInputStream類(lèi),它們的父類(lèi)為InputStream和OutputStream。主要的方法有:●InputStreamintread()
intread(bytebuf[])
intread(bytebuf[],intoffset,intlength)close()●OutputStreamintwrite(intc)intwrite(bytebuf[])intwrite(bytebuf[],intoffset,intlength)close()下麵給出一個(gè)應(yīng)用實(shí)例7.4。圖7.5
例7.4
importjava.io.*;publicclassFileCopy{publicstaticvoidmain(Stringargs[])throwsIOException{FileInputStreamf1;FileOutputStreamf2;f1=newFileInputStream("FileCopy.java");f2=newFileOutputStream("acopy_of_java_file");
inttemp;while((temp=f1.read())!=-1)
f2.write(temp);
f1.close();f1.close();}
publicFileCopy(){}}
在該例中,我們利用位元組流將本程式拷貝至另一個(gè)檔acopy_of_java_file中,如果指定的檔不存在,則創(chuàng)建一個(gè)新檔,否則原文件的內(nèi)容會(huì)被新寫(xiě)入的內(nèi)容覆蓋。當(dāng)程式運(yùn)行後,將生成一個(gè)與原程式相同的副本。2.Character流(字元流)檔的讀取該類(lèi)如圖7.2所示,輸入/輸出類(lèi)的父類(lèi)為Reader、Writer,其基本的方法有:●Reader
intread()
intread(charbuf[])
intread(charbuf[],intoffset,intlength)close()●Writer
intwrite(intc)
intwrite(charbuf[])
intwrite(charbuf[],intoffset,intlength)close()
讀者可與位元組流進(jìn)行比較,注意二者方法的區(qū)別。下麵我們用字符流來(lái)改寫(xiě)例7.4:
例7.5
importjava.io.*;publicclassFileCopy{
publicstaticvoidmain(Stringargs[])throwsIOException{FileReaderf1;FileWriterf2;f1=newFileReader("FileCopy.java");f2=newFileWriter("acopy_of_java_file");inttemp;while((temp=f1.read())!=-1)f2.write(temp);f1.close();f2.close();}publicFileCopy(){}}例7.6importjava.io.*;publicclassReadFile{ publicstaticvoidmain(String[]args) throwsIOException{ FileReaderfr=newFileReader("ReadFile.java"); BufferedReaderbr=newBufferedReader(fr); Stringline=br.readLine(); while(line!=null){Transcript.println(line);
line=br.readLine(); } br.close();
}}
本程式中,我們通過(guò)類(lèi)BufferedReader對(duì)檔實(shí)現(xiàn)按行讀取,達(dá)到一行一行輸出的目的,結(jié)果如圖7.6所示。圖7.63.二進(jìn)位數(shù)據(jù)流的檔讀取如果要讀取與機(jī)器無(wú)關(guān)的基本數(shù)據(jù)類(lèi)型的數(shù)據(jù),如整型或浮點(diǎn)型的二進(jìn)位數(shù),就要用到二進(jìn)位數(shù)據(jù)檔流DataInputStream、DataOutputStream。實(shí)際使用中,類(lèi)DataInputStream和DataOutputStream必須和一個(gè)輸入類(lèi)(InputStream)或輸出類(lèi)(OutputStream)聯(lián)接起來(lái),不能直接用檔案名或檔對(duì)象(File)對(duì)其直接初始化,例如:例7.7importjava.io.*;publicclassDatastreamDemo{publicstaticvoidmain(Stringargs[])throwsIOException{FileOutputStreamf2=newFileOutputStream("data");DataOutputStreamdfo=newDataOutputStream(f2);dfo.writeBoolean(true);
dfo.writeInt(100);dfo.writeFloat(200.2f);f2.close();dfo.close();FileInputStreamf1=newFileInputStream("data");DataInputStreamdfi=newDataInputStream(f1);booleanb=dfi.readBoolean();inti=dfi.readInt();floatf=dfi.readFloat();f1.close();dfi.close();Transcript.println("Thevalueis:");Transcript.println(""+b);Transcript.println(""+i);Transcript.println(""+f);}
publicDatastreamDemo(){}}
該例中,我們首先利用類(lèi)DataOutputStream生成一個(gè)二進(jìn)位檔data,並對(duì)它寫(xiě)入三個(gè)不同類(lèi)型的數(shù)據(jù):布爾型、整型、浮點(diǎn)型。然後利用DataInputStream讀入剛剛輸入的數(shù)據(jù)並顯示出來(lái),結(jié)果如圖7.7所示??梢钥闯?,輸出結(jié)果與我們的輸入是一一對(duì)應(yīng)的。圖7.74.隨機(jī)訪問(wèn)檔的讀取對(duì)於InputStream/OutputStream、Reader/Writer類(lèi)來(lái)說(shuō),它們都是順序訪問(wèn)流,只能進(jìn)行順序讀寫(xiě)。而所謂隨機(jī)讀寫(xiě),是指讀寫(xiě)完上一個(gè)位元組後,不只能讀寫(xiě)其後繼的位元組,還可以讀寫(xiě)檔中任意的位元組,就好象檔中有一個(gè)隨意移動(dòng)的指針一樣。
Java語(yǔ)言提供了類(lèi)RandomAccessFile來(lái)進(jìn)行隨機(jī)檔的讀取。在生成一個(gè)RandomAccessFile對(duì)象時(shí),不僅要說(shuō)明文件對(duì)象或檔案名,同時(shí)還需指明訪問(wèn)模式,即“只讀方式”(r)或“讀寫(xiě)方式”(rw),這類(lèi)似於C/C++中的fopen()函數(shù)。
RandomAccessFile類(lèi)的功能類(lèi)似於DataOutputStream類(lèi)和DataInputStream類(lèi)的功能合併,即實(shí)現(xiàn)了在一個(gè)流中進(jìn)行讀、寫(xiě)兩種功能。其常用的方法如表7.2所示。表7.2RandomAccessFile類(lèi)的常用方法方法名功能描述longgetFilePointer()返回當(dāng)前檔指針longlength()返回檔長(zhǎng)度booleanreadBoolean()讀入一個(gè)布爾值intreadInt()讀入一個(gè)整數(shù)stringreadLine()讀入一行字串voidseek(longpos)檔指針移到指定位置intskipBytes(intn)檔指針向前移n個(gè)位元組voidwrite(byteb[])把數(shù)組內(nèi)容寫(xiě)入檔voidwriteBoolean(booleanv)寫(xiě)入一個(gè)布爾值voidwriteInt(intv)寫(xiě)入一個(gè)整數(shù)
例7.8的功能與例7.7一樣,只不過(guò)是用RandomAccessFile來(lái)實(shí)現(xiàn)的。例7.8importjava.io.*;publicclassRandomDemo{publicstaticvoidmain(Stringargs[])throwsIOException{RandomAccessFilefa=newRandomAccessFile("data","rw");
fa.writeBoolean(true);fa.writeInt(100);fa.writeFloat(200.2f);fa.seek(0);booleanb=fa.readBoolean();inti=fa.readInt();floatf=fa.readFloat();Transcript.println("Thevaluereadfromarandomfileis:");Transcript.println(""+b);Transcript.println(""+i);Transcript.println(""+f);
fa.close();}publicRandomDemo(){}}程式運(yùn)行結(jié)果如圖7.8所示。圖7.87.3特殊的I/O處理流
除了前面我們介紹的一些常用的輸入/輸出流之外,java.io包中提供了很多特殊的輸入/輸出流,我們可描述如表7.3所示。類(lèi)型說(shuō)明流類(lèi)功能描述管道流PipedReaderPipedWriterPipedInputStreamPipedOutputStream用於在不同的線程或進(jìn)程之間進(jìn)行資訊傳遞記憶體流CharArrayReaderCharArrayWriterByteArrayInputStreamByteArrayOutputStream用於在內(nèi)存中進(jìn)行讀/寫(xiě),往往借助於數(shù)組,通過(guò)read()或write()方法從數(shù)組中讀/寫(xiě)數(shù)據(jù)StringReaderStringWriterStringBufferInputStream從存在於記憶體的一個(gè)字串中讀/寫(xiě)數(shù)據(jù)輸入流的連接SequenceInputStream將多個(gè)InputStream連接起來(lái)順序進(jìn)行輸入過(guò)濾流FilterReaderFilterWriterFilterInputStreamFilterOutputStream特定的抽象類(lèi),須擴(kuò)展解析流StreamTokenizer用於對(duì)字串的解析表7.3java.io包中的特殊輸入/輸出流表7.3java.io包中的特殊輸入/輸出流7.3.1管道流管道流(PipedStream)可用來(lái)把一個(gè)程式、線程或代碼段的輸出直接連接到另一個(gè)程式、線程或代碼段的輸入。Java中管道的類(lèi)有PipedReader、PipedWriter、PipedInputStream及PipedOutputStream。使用過(guò)程中,管道輸入流作為一個(gè)通信管道的接收端進(jìn)行數(shù)據(jù)的讀取,管道輸出流作為發(fā)送端進(jìn)行數(shù)據(jù)的傳送。下麵我們先看一個(gè)實(shí)例:例7.9importjava.io.*;publicclassPipedDemo{publicstaticvoidmain(Stringargs[])throwsIOException{PipedWriterpw=newPipedWriter();PipedReaderpr=newPipedReader(pw);newRead(pw,"ReadFile.txt").start();newWrite(pr,"WriteFile.txt").start();}publicPipedDemo(){ }}importjava.io.*;publicclassWriteextendsThread{PipedReaderpr;Filef;Write(PipedReaderpr,Stringf){this.pr=pr;this.f=newFile(f);}publicvoidrun(){try{FileWriterfw=newFileWriter(f);
intdata;while((data=pr.read())!=-1)fw.write(data);fw.close();}catch(IOExceptione){}}publicWrite(){}}importjava.io.*;publicclassReadextendsThread{PipedWriterpw;Filef;Read(PipedWriterpw,Stringf){this.pw=pw;this.f=newFile(f);}
publicvoidrun(){try{FileReaderfr=newFileReader(f);intdata;while((data=fr.read())!=-1)pw.write(data);pw.close();}catch(IOExceptione){}}
在本例中,我們通過(guò)定義兩個(gè)線程進(jìn)行管道PipedReader、PipedWriter的連接。線程的概念讀者可參考後面章節(jié)的內(nèi)容,這裏只要把其理解為可以同時(shí)工作的兩段程式就可以了。程式運(yùn)行後,WriteFile.txt的內(nèi)容就從檔ReadFile.txt中完全拷貝過(guò)來(lái)。在管道流的初始化過(guò)程中,可以給出對(duì)應(yīng)的管道輸入/輸出流作為參數(shù)進(jìn)行連接,如本例:
PipedReaderpr=newPipedReader(PipedWriterpw);
或 PipedWriterpw=newPipedWriter(PipedReaderpr);
在Java中,管道輸入/輸出流還可以通過(guò)方法connect()進(jìn)行連接,如把本例中的程式改為
PipedWriterpw=newPipedWriter();PipedReaderpr=newPipedReader(); pr.connect(pw);
效果是一樣的。讀者也可用管道流PipedInputStream、PipedOutputStream來(lái)實(shí)現(xiàn)上例,這裏留給讀者自己練習(xí)。7.3.2記憶體的I/O流表7.3給出了Java支持記憶體讀/寫(xiě)的類(lèi),總結(jié)起來(lái)有以下兩類(lèi)。
(1)對(duì)應(yīng)位元組記憶體讀/寫(xiě)的有ByteArrayInputStream、ByteArrayOutputStream及String
BufferInputStream。它們可以從位元組數(shù)組中讀取數(shù)據(jù)或向位元組數(shù)組中寫(xiě)入數(shù)據(jù)。例如:例7.10importjava.io.*;publicclassMemoryDemo{publicstaticvoidmain(Stringargs[])throwsIOException{byteb[]={111,100,74,98,80,69};bytetemp[]=newbyte[10];ByteArrayInputStreambi=newByteArrayInputStream(b);ByteArrayOutputStreambo=newByteArrayOutputStream();StringBufferInputStreambs=newStringBufferInputStream("Ademoformemoryinput!");intx;while((x=bi.read())!=-1)
bo.write(x);Transcript.println("TheresultofByteArrayOutputStreamis:"+bo);bs.read(temp,0,4);Transcript.print("TheresultofStringBufferOutputStreamis:");for(inti=0;i<=3;i++)Transcript.print(""+temp[i]);Transcript.println();Transcript.print(""+bs);}}
運(yùn)行結(jié)果如圖7.9所示。圖7.9
對(duì)於ByteArrayOutputStream來(lái)說(shuō),我們先從ByteArrayInputStream類(lèi)中把位元組流讀入bo的緩衝區(qū)中,然後直接進(jìn)行輸出,該對(duì)象調(diào)用自己的toString()進(jìn)行輸出格式轉(zhuǎn)換。
(2)對(duì)應(yīng)字元記憶體讀/寫(xiě)的有CharArrayReader、CharArrayWriter、StringReader及StringWriter。它們可以從字元數(shù)組中讀取數(shù)據(jù)或向字元數(shù)組中寫(xiě)入數(shù)據(jù)。例如:例7.11
importjava.io.*;publicclassMemoryDemo{publicstaticvoidmain(Stringargs[])throwsIOException{charb[]={'a','t','e','s','t','d','e','m','o'};chartemp[]=newchar[10];CharArrayReaderbr=newCharArrayReader(b);CharArrayWriterbw=newCharArrayWriter();StringReaderbsr=newStringReader("testdemo!");StringWriterbsw=newStringWriter();intx;while((x=br.read())!=-1)bw.write(x);Transcript.println("TheresultofCharArrayReaderis:"+bw);bsr.read(temp,0,4);Transcript.print("TheresultofStringReaderis:");for(inti=0;i<=3;i++)Transcript.print(""+temp[i]);Transcript.println();bsw.write("hello,everybody!");Transcript.print("TheresultofStringWriteris:");Transcript.println(""+bsw);}}
程式運(yùn)行結(jié)果如圖7.10所示。圖7.10
我們可以發(fā)現(xiàn)以上兩個(gè)程式的基本架構(gòu)無(wú)大的區(qū)別,只是對(duì)不同記憶體流,構(gòu)造方法有所不同。上述的幾種輸出記憶體流,它們?cè)诔跏蓟臅r(shí)候,缺省的緩衝區(qū)的大小均為32個(gè)位元組。當(dāng)然,實(shí)際操作過(guò)程中,緩衝區(qū)的大小會(huì)隨數(shù)據(jù)的寫(xiě)入自動(dòng)增加。不同的類(lèi)會(huì)有多種不同的方法,方法的使用建立在對(duì)各種流的熟悉程度之上,讀者應(yīng)盡可能的學(xué)習(xí)Java聯(lián)機(jī)文檔的內(nèi)容,獲取更多的知識(shí)。7.3.3多個(gè)輸入流的連接如果我們?cè)趯?duì)檔的操作中需要讀取多個(gè)檔的話,可使用Java所提供的SequenceInputStream類(lèi)。該類(lèi)把多個(gè)檔連接起來(lái),形成多個(gè)連接的順序輸入流,該流依次打開(kāi)每個(gè)輸入流,讀取數(shù)據(jù),然後關(guān)閉該流,並自動(dòng)切換到下一個(gè)輸入流。它的兩種構(gòu)造方法如下:
SequenceInputStream(Enumeratione); SequenceInputStream(InputStreams1,InputStreams2);其中,Enumeration類(lèi)為一介面,處在Java中的util包中,它包含兩個(gè)方法:
publicObjectnextElement() publicbooleanhasMoreElements()
方法nextElement()取得集合中的下一個(gè)對(duì)象;方法hasMoreElements()測(cè)試集合中的元素是否已經(jīng)全部取完,並返回一個(gè)布爾值。下麵是一個(gè)利用順序流對(duì)指定的兩個(gè)檔進(jìn)行合併操作的例子。例7.12importjava.io.*;importjava.util.*;publicclassConcaDemo{publicstaticvoidmain(Stringargs[])throwsIOException{Strings[]=newString[2];s[0]="PipedDemo.java";s[1]="MemoryDemo.java";Filesflist=newFiles(s);SequenceInputStreamsi=newSequenceInputStream(flist);FileOutputStreamfo=newFileOutputStream("concaFile.txt");intc;while((c=si.read())!=-1)fo.write(c);si.close();fo.close();}}importjava.io.*;importjava.util.*;publicclassFilesimplementsEnumeration{privateString[]listofFiles;privateintcurrent=0;publicFiles(String[]listofFiles){this.listofFiles=listofFiles;}publicbooleanhasMoreElements(){if(current<listofFiles.length)returntrue;elsereturnfalse;}publicObjectnextElement(){try{if(!hasMoreElements())returnnull;else{current++;returnnewFileInputStream(listofFiles[current-1]);}}catch(Exceptione){returnnull;}
}}
當(dāng)我們?cè)贘Builder中運(yùn)行該程式後,檔concaFile.txt就合併了PipedDemo.java及MemoryDemo.java中的內(nèi)容。7.3.4過(guò)濾流過(guò)濾流在讀/寫(xiě)數(shù)據(jù)的同時(shí)可以對(duì)數(shù)據(jù)進(jìn)行處理。Java提供了多個(gè)具有過(guò)濾功能的輸入/輸出類(lèi),位元組類(lèi)過(guò)濾流的父類(lèi)均為FilterInputStream、FilterOutputStream。這兩個(gè)類(lèi)為抽象類(lèi),包含的子類(lèi)有:
DataInputStream/DataOutputStreamBufferedInputStream/BufferedOutputStreamLineNumberInputStreamPushbackInputStreamPrintStream
FilterReader/FilterWriter
過(guò)濾流是建立在其他流之上的,也就是說(shuō),當(dāng)使用一個(gè)過(guò)濾流時(shí),必須首先把過(guò)濾流連接到某個(gè)輸入/輸出流上。比如,可以通過(guò)輸入過(guò)濾流的方法read()從下層流中讀取數(shù)據(jù),通過(guò)輸出過(guò)濾流的write()方法把數(shù)據(jù)寫(xiě)入下層流。
不同過(guò)濾流實(shí)現(xiàn)不同的過(guò)濾功能,例如:數(shù)據(jù)的暫存、數(shù)據(jù)的統(tǒng)計(jì)、數(shù)據(jù)的轉(zhuǎn)換等等。讀者對(duì)上述的一些類(lèi)也不必死記,使用的時(shí)候,查看相關(guān)的聯(lián)機(jī)幫助文檔便可獲得詳細(xì)的內(nèi)容。下麵我們分兩部分來(lái)對(duì)過(guò)濾流加以介紹:首先介紹如何使用Java系統(tǒng)提供的過(guò)濾流類(lèi),之後,介紹如何定義自己的過(guò)濾流。1.使用過(guò)濾流類(lèi)BufferedInputStream/BufferedOutputStream實(shí)現(xiàn)了帶緩衝的過(guò)濾流。進(jìn)行網(wǎng)路編程時(shí),當(dāng)需要在不同線程之間傳送數(shù)據(jù)時(shí),使用緩衝流會(huì)得到較高的性能。數(shù)據(jù)的輸入/輸出均是首先讀入/寫(xiě)出到緩衝區(qū)中,對(duì)BufferedOutputStream來(lái)說(shuō),當(dāng)數(shù)據(jù)緩衝區(qū)滿(mǎn)時(shí),就可以寫(xiě)入所連接的輸出流,它所提供的flush()也可強(qiáng)制緩衝區(qū)的內(nèi)容在任何時(shí)候全部寫(xiě)入輸出流。
過(guò)濾流DataInputStream、DataOutputStream實(shí)現(xiàn)了介面DataInput、DataOutput。它們可以從所連接的輸入流中讀取與機(jī)器無(wú)關(guān)的基本數(shù)據(jù)類(lèi)型,也可以向所連接的輸出流寫(xiě)入基本類(lèi)型數(shù)據(jù)。這一點(diǎn)我們可以從例7.7看出。類(lèi)PrintStream所提供的方法print()、println()可以輸出各種類(lèi)型數(shù)據(jù),只是後一種方法在輸入結(jié)束時(shí)自動(dòng)換行。我們可以利用生成該類(lèi)的實(shí)例進(jìn)行不同數(shù)據(jù)的輸出。下麵我們給出應(yīng)用過(guò)濾流的具體實(shí)例:
例7.13importjava.io.*;publicclassFilterIODemo{publicstaticvoidmain(Stringargs[])throwsIOException{DataInputStreamdi=newDataInputStream(newBufferedInputStream(System.in));PrintStreampo=newPrintStream(newBufferedOutputStream(System.out));Strings;s=di.readLine();while(!s.equals("seeyou!")){po.println("Result:"+s);po.flush();s=di.readLine();}di.close();po.close();}publicFilterIODemo(){}}
本例中,System.in、System.out是系統(tǒng)的標(biāo)準(zhǔn)輸入/輸出類(lèi),這裏我們指的是控制臺(tái),即鍵盤(pán)和螢?zāi)弧T摱纬淌竭\(yùn)行時(shí),用戶(hù)可不斷輸入一些字元,輸入的字元會(huì)立即顯示在螢?zāi)簧?,直到某一行輸入的字元中有“seeyou!”時(shí),程式結(jié)束運(yùn)行。結(jié)果如圖7.11所示。圖7.11例7.14
importjava.io.*;publicclassPushbackDemo{publicstaticvoidmain(Stringargs[])throwsIOException{PushbackInputStreampis=newPushbackInputStream(System.in);intdata;data=pis.read();while(!Character.isLetter((char)data))data=pis.read();pis.unread(data);while(true){data=pis.read();if(Character.isLetter((char)data))Transcript.print(""+(char)data);}}publicPushbackDemo(){}}
程式中語(yǔ)句:
while(!Character.isLetter((char)data))
data=pis.read();
pis.unread(data);
的作用是把開(kāi)頭的白字符(whitecharacter)過(guò)濾掉,並且回吐給輸入流過(guò)濾掉的第一個(gè)字元。2.創(chuàng)建自己的過(guò)濾流程式的編寫(xiě)過(guò)程中,往往需要實(shí)現(xiàn)自己的過(guò)濾流以在讀/寫(xiě)操作時(shí)可以對(duì)數(shù)據(jù)進(jìn)行特定的處理,這時(shí)就必須自己定義繼承於FilterInputStream、FilterOutputStream的過(guò)濾流。如果有必要,需重載方法read()、write()或其他一些方法,同時(shí)應(yīng)該確保輸入/輸出流一起工作。請(qǐng)看下例。例7.15
importjava.io.*;publicclassMain{publicstaticvoidmain(Stringargs[])throwsIOException{InputStreamfin=newFileInputStream("ReadFile.txt");OutputStreamstdout=newFileOutputStream(FileDescriptor.out);MyInputStreamnis=newMyInputStream(fin);MyOutputStreamnos=newMyOutputStream(stdout);while(true)nos.write(nis.read());}publicMain(){}}importjava.io.*;publicclassMyInputStreamextendsFilterInputStream{publicintread()throwsIOException{
intdata=in.read();StringBuffersb=newStringBuffer();while(data!=-1&&!Character.isDigit((char)data))data=in.read();while(data!=-1&&Character.isDigit((char)data)){sb.append((char)data);data=in.read();}returnInteger.parseInt(sb.toString());}publicMyInputStream(InputStreamin){super(in);}}importjava.io.*;publicclassMyOutputStreamextendsFilterOutputStream{publicvoidwrite(intb)throwsIOException{System.out.println("NowinOutputStreamis:");Stringdata=Integer.toString(b);bytechar_array[]=newbyte[data.length()];data.getBytes(0,data.length(),char_array,0);out.write(char_array);}publicMyOutputStream(OutputStreamout){super(out);}}
本例中,定義了兩個(gè)類(lèi):MyInputStream和MyOutputStream,它們均從過(guò)濾流FilterInputStream、FilterOutputStream繼承而來(lái),同時(shí)重寫(xiě)了父類(lèi)中的read()、write()方法。在類(lèi)MyInputStream的read()方法中,可以讀出檔中所有的數(shù)字運(yùn)算式。因?yàn)槲覀儊K沒(méi)有對(duì)所有的例外進(jìn)行捕獲,所以,類(lèi)Main中的語(yǔ)句“while(true)”雖是無(wú)限迴圈,但最終卻能由例外NumberFormatException中斷。在類(lèi)MyOutputStream中,由於沒(méi)有相關(guān)的輸出字元方法,如DataInputStream中的writeChar()方法,因而我們首先把數(shù)字轉(zhuǎn)換為一個(gè)位元組數(shù)組,然後進(jìn)行輸出。假如檔ReadFile.txt的內(nèi)容為Number:124589100 Score:65892288則最後的輸出結(jié)果為SystemOutput: NowinOutputStreamis:SystemOutput: 12SystemOutput: NowinOutputStreamis:SystemOutput: 45SystemOutput: NowinOutputStreamis:SystemOutput: 89SystemOutput: NowinOutputStreamis:SystemOutput: 100SystemOutput: NowinOutputStreamis:SystemOutput: 65SystemOutput: NowinOutputStreamis:SystemOutput: 89SystemOutput: NowinOutputStreamis:SystemOutput: 22SystemOutput: NowinOutputStreamis:SystemOutput: 887.3.5解析流
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年度醫(yī)院醫(yī)療廢物處理設(shè)施建設(shè)合同4篇
- 2025年度個(gè)人創(chuàng)業(yè)貸款合同示范文本8篇
- 二零二五年度美容院美容護(hù)膚品生產(chǎn)股份合作合同4篇
- 二零二五版木質(zhì)家具定制設(shè)計(jì)與生產(chǎn)加工合同3篇
- 二零二五年度電子商務(wù)平臺(tái)標(biāo)志設(shè)計(jì)及用戶(hù)體驗(yàn)合同3篇
- 二零二五年度托盤(pán)租賃與供應(yīng)鏈金融結(jié)合合同范本3篇
- 二零二五年度昌平區(qū)食堂員工激勵(lì)與績(jī)效考核合同3篇
- 2025年度汽車(chē)租賃與品牌合作推廣合同范本3篇
- 二零二五年度城市綠化工程承包合同14篇
- 2025年度線上線下聯(lián)動(dòng)大型促銷(xiāo)活動(dòng)合作合同3篇
- 項(xiàng)目前期選址分析報(bào)告
- 急性肺栓塞搶救流程
- 《統(tǒng)計(jì)學(xué)-基于Python》 課件全套 第1-11章 數(shù)據(jù)與Python語(yǔ)言-時(shí)間序列分析和預(yù)測(cè)
- 《形象價(jià)值百萬(wàn)》課件
- 紅色文化教育國(guó)內(nèi)外研究現(xiàn)狀范文十
- 中醫(yī)基礎(chǔ)理論-肝
- 小學(xué)外來(lái)人員出入校門(mén)登記表
- 《土地利用規(guī)劃學(xué)》完整課件
- GB/T 25283-2023礦產(chǎn)資源綜合勘查評(píng)價(jià)規(guī)范
- 《汽車(chē)衡全自動(dòng)智能稱(chēng)重系統(tǒng)》設(shè)計(jì)方案
- 義務(wù)教育歷史課程標(biāo)準(zhǔn)(2022年版)
評(píng)論
0/150
提交評(píng)論