Java的輸入輸出流課件_第1頁(yè)
Java的輸入輸出流課件_第2頁(yè)
Java的輸入輸出流課件_第3頁(yè)
Java的輸入輸出流課件_第4頁(yè)
Java的輸入輸出流課件_第5頁(yè)
已閱讀5頁(yè),還剩97頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

Java的輸入/輸出流7.1Java語(yǔ)言I/O的類層次Java輸入/輸出流封裝在包java.io中,其常用的層次結(jié)構(gòu)如圖7.1、7.2所示。除了圖中給出的類外,實(shí)際使用中,我們還會(huì)碰到File類,它用來(lái)描述某個(gè)檔的資訊。輸入/輸出類中還有幾個(gè)比較重要的介面,例如:DataInput、DataOutput、FileNameFilter。後面我們會(huì)作詳細(xì)的介紹。圖7.1圖7.2Java的流方法從結(jié)構(gòu)上可以分為三大類:位元組流、數(shù)據(jù)流和列印流。位元組輸入/輸出流操作對(duì)象為位元組(byte);數(shù)據(jù)流的數(shù)據(jù)比較多,包含所有基本類型的二進(jìn)位數(shù)據(jù);列印流是機(jī)器能夠識(shí)別的字元形式(包括ASCII碼和Unicode碼)。7.2Java中文件的操作

編寫(xiě)程式免不了要經(jīng)常與檔打交道,檔的輸入/輸出需要用到圖7.1中所列出的類FileInputStream、FileOutputStream及RandomAccessFile類。前兩個(gè)類針對(duì)於順序檔的存取,後一個(gè)類用於隨機(jī)檔的讀取。後面我們會(huì)有詳細(xì)的介紹。7.2.1檔與目錄的描述類——FileFile類並不用來(lái)進(jìn)行檔的讀/寫(xiě)操作,它用來(lái)描述檔對(duì)象的屬性,既可以表示檔,也可以表示目錄。使用它提供的方法,我們可以得到所指對(duì)象的描述資訊,包括名稱、存在否、讀/寫(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類的一些方法及說(shuō)明。表7.1File類的方法及變數(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類的應(yīng)用實(shí)例。通過(guò)例題的使用,希望讀者對(duì)File類有更清楚的認(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類的list方法中傳遞參數(shù),這樣,處在目錄c:\\jbuilder3\\myprojects下的所有檔及目錄將均被輸出,結(jié)果如圖7.4所示。

圖7.3圖7.4

程式設(shè)計(jì)中,往往會(huì)碰到根據(jù)某一匹配模式來(lái)查找目錄下的檔的問(wèn)題,這時(shí)就需使用File類帶參數(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流(位元組流)檔的讀取該類的結(jié)構(gòu)如圖7.1所示,我們主要用其中的FileOutputStream和FileInputStream類,它們的父類為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流(字元流)檔的讀取該類如圖7.2所示,輸入/輸出類的父類為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ò)類BufferedReader對(duì)檔實(shí)現(xiàn)按行讀取,達(dá)到一行一行輸出的目的,結(jié)果如圖7.6所示。圖7.63.二進(jìn)位數(shù)據(jù)流的檔讀取如果要讀取與機(jī)器無(wú)關(guān)的基本數(shù)據(jù)類型的數(shù)據(jù),如整型或浮點(diǎn)型的二進(jìn)位數(shù),就要用到二進(jìn)位數(shù)據(jù)檔流DataInputStream、DataOutputStream。實(shí)際使用中,類DataInputStream和DataOutputStream必須和一個(gè)輸入類(InputStream)或輸出類(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(){}}

該例中,我們首先利用類DataOutputStream生成一個(gè)二進(jìn)位檔data,並對(duì)它寫(xiě)入三個(gè)不同類型的數(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)說(shuō),它們都是順序訪問(wèn)流,只能進(jìn)行順序讀寫(xiě)。而所謂隨機(jī)讀寫(xiě),是指讀寫(xiě)完上一個(gè)位元組後,不只能讀寫(xiě)其後繼的位元組,還可以讀寫(xiě)檔中任意的位元組,就好象檔中有一個(gè)隨意移動(dòng)的指針一樣。

Java語(yǔ)言提供了類RandomAccessFile來(lái)進(jìn)行隨機(jī)檔的讀取。在生成一個(gè)RandomAccessFile對(duì)象時(shí),不僅要說(shuō)明文件對(duì)象或檔案名,同時(shí)還需指明訪問(wèn)模式,即“只讀方式”(r)或“讀寫(xiě)方式”(rw),這類似於C/C++中的fopen()函數(shù)。

RandomAccessFile類的功能類似於DataOutputStream類和DataInputStream類的功能合併,即實(shí)現(xiàn)了在一個(gè)流中進(jìn)行讀、寫(xiě)兩種功能。其常用的方法如表7.2所示。表7.2RandomAccessFile類的常用方法方法名功能描述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所示。類型說(shuō)明流類功能描述管道流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特定的抽象類,須擴(kuò)展解析流StreamTokenizer用於對(duì)字串的解析表7.3java.io包中的特殊輸入/輸出流表7.3java.io包中的特殊輸入/輸出流7.3.1管道流管道流(PipedStream)可用來(lái)把一個(gè)程式、線程或代碼段的輸出直接連接到另一個(gè)程式、線程或代碼段的輸入。Java中管道的類有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ě)的類,總結(jié)起來(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類中把位元組流讀入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)增加。不同的類會(huì)有多種不同的方法,方法的使用建立在對(duì)各種流的熟悉程度之上,讀者應(yīng)盡可能的學(xué)習(xí)Java聯(lián)機(jī)文檔的內(nèi)容,獲取更多的知識(shí)。7.3.3多個(gè)輸入流的連接如果我們?cè)趯?duì)檔的操作中需要讀取多個(gè)檔的話,可使用Java所提供的SequenceInputStream類。該類把多個(gè)檔連接起來(lái),形成多個(gè)連接的順序輸入流,該流依次打開(kāi)每個(gè)輸入流,讀取數(shù)據(jù),然後關(guān)閉該流,並自動(dòng)切換到下一個(gè)輸入流。它的兩種構(gòu)造方法如下:

SequenceInputStream(Enumeratione); SequenceInputStream(InputStreams1,InputStreams2);其中,Enumeration類為一介面,處在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ò)濾功能的輸入/輸出類,位元組類過(guò)濾流的父類均為FilterInputStream、FilterOutputStream。這兩個(gè)類為抽象類,包含的子類有:

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ì)上述的一些類也不必死記,使用的時(shí)候,查看相關(guān)的聯(lián)機(jī)幫助文檔便可獲得詳細(xì)的內(nèi)容。下麵我們分兩部分來(lái)對(duì)過(guò)濾流加以介紹:首先介紹如何使用Java系統(tǒng)提供的過(guò)濾流類,之後,介紹如何定義自己的過(guò)濾流。1.使用過(guò)濾流類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ū)滿時(shí),就可以寫(xiě)入所連接的輸出流,它所提供的flush()也可強(qiáng)制緩衝區(qū)的內(nèi)容在任何時(shí)候全部寫(xiě)入輸出流。

過(guò)濾流DataInputStream、DataOutputStream實(shí)現(xiàn)了介面DataInput、DataOutput。它們可以從所連接的輸入流中讀取與機(jī)器無(wú)關(guān)的基本數(shù)據(jù)類型,也可以向所連接的輸出流寫(xiě)入基本類型數(shù)據(jù)。這一點(diǎn)我們可以從例7.7看出。類PrintStream所提供的方法print()、println()可以輸出各種類型數(shù)據(jù),只是後一種方法在輸入結(jié)束時(shí)自動(dòng)換行。我們可以利用生成該類的實(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)輸入/輸出類,這裏我們指的是控制臺(tái),即鍵盤(pán)和螢?zāi)?。該段程式運(yùn)行時(shí),用戶可不斷輸入一些字元,輸入的字元會(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è)類:MyInputStream和MyOutputStream,它們均從過(guò)濾流FilterInputStream、FilterOutputStream繼承而來(lái),同時(shí)重寫(xiě)了父類中的read()、write()方法。在類MyInputStream的read()方法中,可以讀出檔中所有的數(shù)字運(yùn)算式。因?yàn)槲覀儊K沒(méi)有對(duì)所有的例外進(jìn)行捕獲,所以,類Main中的語(yǔ)句“while(true)”雖是無(wú)限迴圈,但最終卻能由例外NumberFormatException中斷。在類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)益歸上傳用戶所有。
  • 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ì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論