《Java程序設(shè)計(jì)基礎(chǔ)》第10章:輸入輸出系統(tǒng).ppt
《《Java程序設(shè)計(jì)基礎(chǔ)》第10章:輸入輸出系統(tǒng).ppt》由會(huì)員分享,可在線閱讀,更多相關(guān)《《Java程序設(shè)計(jì)基礎(chǔ)》第10章:輸入輸出系統(tǒng).ppt(48頁(yè)珍藏版)》請(qǐng)?jiān)谘b配圖網(wǎng)上搜索。
第10章輸入輸出系統(tǒng),學(xué)習(xí)重點(diǎn):輸入輸出的總體結(jié)構(gòu)流的概念構(gòu)建不同的流,第10章輸入輸出系統(tǒng),10.1輸入輸出流的概述10.2各種流的使用10.2.1文件流10.2.2管道流10.2.3連接文件10.2.4過(guò)濾流10.2.5對(duì)象的序列化10.2.6隨機(jī)訪問(wèn)10.3練習(xí)題,10.1輸入輸出流的概述,Java的輸入和輸出多以流的方式進(jìn)行的,它的特點(diǎn)是數(shù)據(jù)的發(fā)送和獲取都是延數(shù)據(jù)序列順序進(jìn)行的,每個(gè)數(shù)據(jù)必須等待它前面的數(shù)據(jù)發(fā)送或讀入后才能被讀寫。,當(dāng)需要讀入數(shù)據(jù)時(shí),程序先從數(shù)據(jù)的來(lái)源(文件、網(wǎng)絡(luò)等)打開一個(gè)流,然后從這個(gè)流中順序讀取數(shù)據(jù)當(dāng)要輸出數(shù)據(jù)時(shí),程序打開一個(gè)流,通過(guò)這個(gè)流向輸出目標(biāo)順序?qū)懭霐?shù)據(jù),1.Character流,Character流以Reader(對(duì)應(yīng)輸入)和Writer(對(duì)應(yīng)輸出)兩個(gè)類族來(lái)實(shí)現(xiàn),其中Reader和Writer是輸入和輸出族的根類,2.Byte流,傳輸8位的數(shù)據(jù)就應(yīng)用Byte流,Java庫(kù)中用InputStream(輸入)和OutputStream(輸出)類族中的類來(lái)實(shí)現(xiàn)8位數(shù)據(jù)的傳輸,這些類主要用來(lái)傳輸二進(jìn)制數(shù)據(jù),如聲音和圖像,ObjectInputStreamObjectOutputStreamy用來(lái)傳輸對(duì)象序列。,3.關(guān)于IO的根類,Reader含有以下讀取字符和字符數(shù)組的方法:intread()intread(charcbuf[])intread(charcbuf[],intoffset,intlength)而InputStream定義了讀取byte型數(shù)據(jù)的方法如下:intread()intread(bytecbuf[])intread(bytecbuf[],intoffset,intlength),Writer方法如下:,intwrite(intc)intwrite(charcbuf[])intwrite(charcbuf[],intoffset,intlength)OutputStream方法如下:intwrite(intc)intwrite(bytecbuf[])intwrite(bytecbuf[],intoffset,intlength),4.各種流簡(jiǎn)介,表10.1列出了java.io包中的各種流和它們的功能。注意,這些流都能傳輸char和byte,兩種不同的數(shù)據(jù)類型。表10.1,10.2各種流的使用,10.2.1文件流文件流(Filestreams)是用來(lái)傳輸當(dāng)前系統(tǒng)下的某個(gè)文件中的一些內(nèi)容的,它應(yīng)該是最簡(jiǎn)單的一種流,它可以是以下幾種流類的對(duì)象:FileReader,F(xiàn)ileWriter,F(xiàn)ileInputStream和FileOutputStream。,例10.1使用FileReader和Filewriter的文件復(fù)制,這個(gè)例子就是把partnovel.txt的內(nèi)容傳輸?shù)絫arget.txt中,這兩個(gè)文件都在本機(jī)的e:\files中。程序代碼,例10.2使用InputStream和OutputStream的文件復(fù)制,程序代碼兩個(gè)方法復(fù)制同樣一段文件內(nèi)容,每次讀取的內(nèi)容是不一樣的,F(xiàn)ileReader每次讀取的是一個(gè)字符(charactor),而屏幕中顯示的是這個(gè)字符的編碼(0到65535之間的一個(gè)整數(shù))。而FileInputStream每次讀取的是一個(gè)字節(jié)(byte),而屏幕中顯示的是這個(gè)字節(jié)的編碼(0~255之間的一個(gè)整數(shù))。,10.2.2管道流,管道流(PipeStreams)是把一個(gè)線程的輸出作為另一個(gè)線程的輸入。實(shí)現(xiàn)它的是PipedReader、PipedWriter、PipedInputStream和PipedOutputStream。,管道流(PipeStreams)的作用,如果定義了一個(gè)類,用來(lái)實(shí)現(xiàn)對(duì)一組詞的操作,其中的一個(gè)操作是按它們的韻(詞尾)排序,方法是先把這些詞的字序逆轉(zhuǎn)(reverse()),然后把逆轉(zhuǎn)后的詞排序(sort()),最后再逆轉(zhuǎn)每個(gè)詞(reverse()),這樣就得到這些詞的韻的排序。,如果不用管道流,這個(gè)操作過(guò)程必須存儲(chǔ)兩個(gè)中間過(guò)程,即經(jīng)過(guò)第一次reverse()后得到的詞表和經(jīng)過(guò)sort()之后的詞表。如圖所示,,Reverse,Reverse,Sort,ListofWords,ListofReversedWords,ListofReversedSortedWords,ListofRhymingWords,而如果用管道流,把一個(gè)方法的輸出作為另一個(gè)方法的輸入,就不需要中間的存儲(chǔ)文件了,當(dāng)然這時(shí)必須用多個(gè)線程同時(shí)運(yùn)行,即revers(),sort()和reverse()一起工作,并且把中間的存儲(chǔ)文件用管道流來(lái)代替。如圖所示。,ListofWords,ListofRhymingWords,例10.3對(duì)詞匯的韻排序,這個(gè)例子中一共定義了3個(gè)類,主要的流程結(jié)構(gòu)定義在RhymingWords類中,它是這個(gè)程序的主類,另外,我們還定義了ReverseThread和SortThread兩個(gè)線程,它們的工作就是分別執(zhí)行上圖中指出的reverse和sort的動(dòng)作,,(1)ReverseThread的作用是執(zhí)行將單詞的字母順序逆轉(zhuǎn)過(guò)來(lái)的動(dòng)作,源代碼如下:,程序代碼這個(gè)線程對(duì)讀入的每一行數(shù)據(jù)調(diào)用了reverseIt()方法,并將逆轉(zhuǎn)完畢的單詞輸出到一個(gè)OutputStream類對(duì)象中去。注意,在這段程序中,我們只使用了普通的輸入輸出流。,,(2)SortThread的作用是對(duì)單詞進(jìn)行排序,其源代碼如下:程序代碼(3)RhymingWords類控制著整個(gè)程序的流程:程序代碼,對(duì)于管道流的使用主要體現(xiàn)在粗體的代碼段,如reverse()方法中的語(yǔ)句:,PipedWriterpipeOut=newPipedWriter();PipedReaderpipeIn=newPipedReader(pipeOut);以上的兩句作用是建立一個(gè)管道,管道的一頭是PipedWriter,另一頭是PipedReader,并且,任何從PipedWriter寫入的內(nèi)容都可以從PipedReader讀出。形成這個(gè)管道的過(guò)程就是在一個(gè)PipedReader上建立一個(gè)PipedWriter。管道流和文件流的主要區(qū)別是文件流必須建立在一個(gè)文件上,而管道流是在兩個(gè)線程之間建立管道,而不是建立在某個(gè)文件或線程上。所以,管道流的建立過(guò)程是先創(chuàng)建一個(gè)空的PipedWriter,然后在PipedWriter上創(chuàng)建PioedReader。程序運(yùn)行時(shí)Reverse線程把內(nèi)容輸入到管道的PipedWriter端,Sort線程從管道的PipedReader端讀出如圖所示。sort()方法中的管道流同樣,只是使用管道的線程不同而已。PipedwriterPipedReaberReversebortThePipe管道的連接,快排序的算法,//這是一個(gè)快排序的方法,它的思路是先設(shè)一個(gè)中間點(diǎn),然后通過(guò)左右對(duì)調(diào)//把值小于中間點(diǎn)的元素放到中間點(diǎn)的左邊,值大于中間點(diǎn)的元素放到右邊//然后對(duì)左右兩部分重復(fù)以上算法,直到完成排序,所以這是一個(gè)遞歸算法假設(shè)Words.txt文件中的內(nèi)容如下:innewBufferedWritersourcePipepipeOutPipedWriterhiflowerairplanecomputernetworkstoppcgamenew,程序代碼,輸出結(jié)果如圖所示,10.2.3連接文件,如果需要讀取多個(gè)文件,并把它們連接在一起,就需要流類SequenceInputStream。,例10.4用一個(gè)流讀取多個(gè)文件并連接,程序首先創(chuàng)建一個(gè)ListOfFiles類的對(duì)象myList來(lái)存放命令行輸入的多個(gè)文件名,然后創(chuàng)建一個(gè)SequenceInputStream對(duì)象,它將按myList指示的順序讀取多個(gè)文件并將它們連接。程序代碼,10.2.4過(guò)濾流,java.io包中提供了一個(gè)類族,這些類實(shí)現(xiàn)過(guò)濾輸入輸出,這些類的根類是FilterInputStream和FilterOutputStream,它們是抽象類。當(dāng)使用過(guò)濾流時(shí),比一般流多一道工序,就是過(guò)濾。過(guò)濾流是建筑在其他流之上的,如過(guò)濾流的方法read()從下層流中讀取數(shù)據(jù),并過(guò)濾后傳給程序,而write()方法是先過(guò)濾后,再把數(shù)據(jù)寫入下層流。,FilterInputStream和FilterOutputStream的子類如下:,DataInputStream和DataOutputStreamBufferedInputStream和BufferedOutputStreamLineNumberInputStreamPushbackInputStreamPrintStream,1.使用過(guò)濾流,要使用過(guò)濾流必須使它附加在其他流上,可以在一個(gè)標(biāo)準(zhǔn)的輸入流上附加一個(gè)過(guò)濾輸入流,例如:BufferedReaderd=newBufferedReader(newDataInputStream(System.in));Stringinput;while((input=d.readLine())!=null){…},例10.5使用DataInputStream和DataOutputStream進(jìn)行過(guò)濾輸入輸出,這個(gè)程序的結(jié)構(gòu)是,首先給出一系列數(shù)據(jù),然后把這些數(shù)據(jù)通過(guò)過(guò)濾流輸出到一個(gè)文件中,最后再?gòu)奈募凶x到屏幕上。程序代碼,2.定義自己的過(guò)濾流,許多時(shí)候我們需要特殊的過(guò)濾方式,而在Java類庫(kù)中沒(méi)有所需的過(guò)濾流,這時(shí)就必須自己定義。定義自己的過(guò)濾流應(yīng)注意以下幾點(diǎn):過(guò)濾流應(yīng)該是DataInputStream和DataOutputStream的子類,而且經(jīng)過(guò)過(guò)濾的數(shù)據(jù)其他方法不能讀出。一般情況下,輸入和輸出是成對(duì)出現(xiàn)的,所以一次定義兩個(gè)流(輸入、輸出)。如果需要,重載read()和write()??梢远x其他的特殊方法完成過(guò)濾。確保輸入和輸出流一起工作。,例10.6創(chuàng)建自己的過(guò)濾流,這個(gè)例子的名字為CheckSum,其作用是判斷從輸入流中讀入的數(shù)據(jù)是否與從輸出流中寫入的數(shù)據(jù)相符,通過(guò)這個(gè)程序,可以實(shí)現(xiàn)在IO方面的多種檢查算法,以保證輸入流與輸出流之間的一致,類似的程序在網(wǎng)絡(luò)管理軟件中經(jīng)常會(huì)用到。這個(gè)例子一共定義了4個(gè)類和一個(gè)接口,它們分別是:過(guò)濾流的兩個(gè)子類:CheckedOutputStream和CheckedInputStream。CheckSum接口以及實(shí)現(xiàn)這個(gè)接口的類Adler32。CheckedIODemo類用于為這個(gè)程序定義main函數(shù)。,(1)CheckedOutputStream類的源代碼如下:,程序代碼在這個(gè)類中,請(qǐng)注意以下幾點(diǎn):首先繼承了FilterOutputStream類,這是自定義過(guò)濾流必要的第一步。然后定義了它的構(gòu)造器,這個(gè)類的構(gòu)造器只有一個(gè),其使用的參數(shù)包括一個(gè)OutputStream類變量,這個(gè)變量即為該過(guò)濾流要過(guò)濾的輸出流,另外一個(gè)參數(shù)是這個(gè)過(guò)濾流的私有變量,它是CheckSum類型的,其作用是用來(lái)更新程序的檢查和。FilterOutputStream中定義了3個(gè)不同的write()方法,這里CheckedOutputStream將這3個(gè)方法都做了重載,每次調(diào)用write()方法時(shí),它都先寫入數(shù)據(jù),然后進(jìn)行檢查并更新檢查和。,(2)CheckedInputStream類的源代碼如下:,程序代碼這個(gè)類與上面的CheckedOutputStream基本上是類似的,它繼承了FilterInputStream,其構(gòu)造器也只有一個(gè),其中的參數(shù)是需要過(guò)濾的輸入流和一個(gè)CheckSum類的私有變量,用來(lái)標(biāo)識(shí)檢查和,并且也將FilterInputStream的3個(gè)read()方法都進(jìn)行了重載,重載的方法就是先讀入數(shù)據(jù),再進(jìn)行檢查。,(3)CheckSum接口的源代碼如下:,interfaceChecksum{publicvoidupdate(intb);publicvoidupdate(byte[]b,intoff,intlen);publiclonggetValue();publicvoidreset();},下面的類來(lái)具體實(shí)現(xiàn)了檢查動(dòng)作。,(4)Adler32類的源代碼如下:程序代碼這個(gè)類使用了CRC-32(循環(huán)冗余)算法對(duì)輸入、輸出流進(jìn)行檢查,我們不用關(guān)心這段程序每個(gè)方法內(nèi)部程序是什么意思,只要注意一下,Adler32類實(shí)現(xiàn)了CheckSum接口的所有方法就可以了。,(5)CheckedIODemo類的源代碼,除了上面介紹的幾個(gè)類和接口之外,還有這樣一些程序段,其作用是控制整個(gè)程序的流程,源代碼如下:程序代碼,假設(shè)farrago.txt文件中存有下面一些內(nèi)容:,Soshewentintothegardentocutacabbage-leaf,tomakeanapple-pie;andatthesametimeagreatshe-bear,comingupthestreet,popsitsheadintotheshop.What!nosoap?Sohedied,andsheveryimprudentlymarriedthebarber;andtherewerepresentthePicninnies,andtheJoblillies,andtheGaryalies,andthegrandPanjandrumhimself,withthelittleroundbuttonattop,andtheyallfelltoplayingthegameofcatchascatchcan,tillthegunpowderranoutattheheelsoftheirboots.SamuelFoote1720-1777我們將得到如下運(yùn)行結(jié)果:Inputstreamchecksum:736868089Outputstreamchecksum:736868089,10.2.5對(duì)象的序列化,1.序列化對(duì)象ObjectInputStream和ObjectOutputStream必須建筑在其他流類的基礎(chǔ)上,這和過(guò)濾流相似。如果把一個(gè)對(duì)象看做一個(gè)活動(dòng)房屋,ObjectOutputStream和ObjectInputStream就是把房屋拆散和重新組裝,當(dāng)然這個(gè)過(guò)程是有一定順序的,而其他的流類就負(fù)責(zé)零件的運(yùn)輸。我們先看ObjectOutputStream,這是拆的過(guò)程。,例10.7對(duì)象序列化,程序代碼這個(gè)例子中的ObjectOutputStream和ObjectInputStream都是建立在FileOutputStream和FileInputStream之上的(粗體部分),然后通過(guò)sOut和sIn的方法writeObject()和readObject()來(lái)輸入和輸出對(duì)象,這里被傳輸?shù)膶?duì)象是字符串“thetime:”和Date類實(shí)例。ObjectOutputStream實(shí)現(xiàn)了接口DataOutput,這個(gè)接口定義了許多輸出簡(jiǎn)單數(shù)據(jù)的方法,如writeInt(),writeFloat()和writeUTF等,讀者可以用這些方法直接把簡(jiǎn)單數(shù)據(jù)寫入ObjectOutputStream。與之對(duì)應(yīng)ObjectInputStream有多個(gè)讀入簡(jiǎn)單數(shù)據(jù)的方法,如readInt(),readFloat()等等。,2.定義能序列化的類,一個(gè)類只有實(shí)現(xiàn)了接口Serializable,它的對(duì)象才能被序列化。這聽起來(lái)很麻煩,事實(shí)上,Serializable接口是個(gè)空接口,它不含有任何方法,下面就是這個(gè)接口的定義:packagejava.io;publicinterfaceSerializable{};//很幸運(yùn),括號(hào)內(nèi)沒(méi)有任何東西這樣我們要使某個(gè)類的對(duì)象可被序列化,只需要在這個(gè)類的類頭聲明實(shí)現(xiàn)接口Serializable,而它的其他定義不用進(jìn)行絲毫改動(dòng),例如:publicclassMySerializableClassimplementsSerializable{…}如何對(duì)對(duì)象進(jìn)行序列化一般不需要編程者自己定義defaultWriteObject()方法來(lái)處理這件事defaultReadObject()方法類重組對(duì)象這兩個(gè)方法分別被writeObject()和readObject()及其他方法調(diào)用。默認(rèn)的序列化方法比較慢。,如果需要還是可以在序列化之后進(jìn)行其他操作,這就要重載writeObject()和readObject()。但調(diào)用默認(rèn)的序列化方法必須放在第一句,如同下面的格式:,privatevoidwriteObject(ObjectOutputStreams)throwsIOException{s.defaultWriteObject();…//自定義部分}privatevoidreadObject(ObjectInputStreams)throwsIOException,ClassNotFoundException{s.defaultReadObject();…//自定義部分},10.2.6隨機(jī)訪問(wèn),首先我們看一下為什么需要隨機(jī)訪問(wèn)。假如有一個(gè)ZIP文檔,大家知道這是一個(gè)壓縮文檔,里面可能包含多個(gè)文件,在ZIP文檔的最后由各個(gè)文件的索引。它的結(jié)構(gòu)如圖10.11所示。,當(dāng)我們需要取出其中的一個(gè)文件時(shí),如果用順序訪問(wèn)必須經(jīng)過(guò)下面4個(gè)步驟:,(1)打開ZIP文檔。(2)順序查找這個(gè)文檔,直到找到所需要的文件。(3)解壓縮這個(gè)文件。(4)關(guān)閉ZIP文檔。可以看出,如果用這種算法,當(dāng)找到所需文件時(shí)平均需要讀取半個(gè)文檔,所以這個(gè)算法的效率是很低的。但如果用隨機(jī)訪問(wèn)方法就不會(huì)這樣,我們只需找到文檔最后的索引,然后根據(jù)索引找到文件的位置,直接解壓縮文件,然后關(guān)閉ZIP文檔。,,RandomAccessFile類和前面的輸入輸出流不同,它把輸入輸出放到一個(gè)類中,通過(guò)其不同的構(gòu)造函數(shù)來(lái)確定是輸出還是輸入。并且它是一個(gè)獨(dú)立分支的類,并不是InputStream或OutputStream的衍生類RandomAccessFile類可以隨機(jī)訪問(wèn)本機(jī)的某個(gè)文件,只要必須提供這個(gè)文件的名稱或代表這個(gè)文件的File類對(duì)象,這點(diǎn)和FileInputStream、FileOutputStream相似。下面是創(chuàng)建隨機(jī)訪問(wèn)的實(shí)例,構(gòu)造函數(shù)中的第二個(gè)參數(shù)只有“r”(只讀)或“rw”(可讀寫)。newRandomAccessFile("partnovel.txt","r");//創(chuàng)建一個(gè)對(duì)文件partnovel的只讀隨機(jī)訪問(wèn)newRandomAccessFile("farrago.txt","rw");//創(chuàng)建一個(gè)對(duì)文件farrago的可讀寫隨機(jī)訪問(wèn)一旦建立了對(duì)文件的隨機(jī)訪問(wèn),就可以使用read()和write()方法了,如readInt(),readFloat(),writeInt()等等。,下面是3個(gè)操縱指針的方法:,intskipBytes(int)//讓指針移動(dòng)跳過(guò)形參指示的字?jǐn)?shù),形參單位是bytevoidseek(long)//把指針從起始位移動(dòng)到形參指示位置,形參單位是bytelonggetFilePointer()//獲取當(dāng)前指針位置(相對(duì)于起始位),例10.8使用隨機(jī)訪問(wèn)類,這個(gè)例子就是用來(lái)對(duì)partnovel.txt進(jìn)行隨機(jī)讀取,其中用n表示從文件頭開始忽略的多少字。程序代碼,10.3練習(xí)題,1.選擇題(1)Character流與Byte流的區(qū)別在于:A.每次讀入的字節(jié)數(shù)不同B.前者帶有緩沖,后者沒(méi)有C.前者是塊讀寫,后者是字節(jié)讀寫D.二者沒(méi)有區(qū)別,可以互換使用,,(2)如果要讀取一個(gè)大文件的末尾的一段內(nèi)容,并且知道該段落的確切位置,最方便的流是:A.FilestreamB.PipedstreamC.RandomaccessstreamD.Filterstream,2.程序閱讀題,下述程序段的執(zhí)行效率是否良好,如何修改能夠提高?inti;URLurl=newURL(",3.編程題,(1)把一些數(shù)據(jù)加到一個(gè)文件的末尾。(2)用PushbackInputStream或PushbackReader實(shí)現(xiàn)逐詞讀取一個(gè)文件的內(nèi)容(用這兩個(gè)類來(lái)提前檢查空格,以確定一個(gè)詞)。(3)實(shí)現(xiàn)一對(duì)Reader和Writer,給輸入、輸出特殊的字母計(jì)數(shù),如輸出的文件中有多少個(gè)a,這個(gè)字母必須容易更改。(4)實(shí)現(xiàn)一個(gè)可序列化的對(duì)象并進(jìn)行傳輸。,- 1.請(qǐng)仔細(xì)閱讀文檔,確保文檔完整性,對(duì)于不預(yù)覽、不比對(duì)內(nèi)容而直接下載帶來(lái)的問(wèn)題本站不予受理。
- 2.下載的文檔,不會(huì)出現(xiàn)我們的網(wǎng)址水印。
- 3、該文檔所得收入(下載+內(nèi)容+預(yù)覽)歸上傳者、原創(chuàng)作者;如果您是本文檔原作者,請(qǐng)點(diǎn)此認(rèn)領(lǐng)!既往收益都?xì)w您。
下載文檔到電腦,查找使用更方便
9.9 積分
下載 |
- 配套講稿:
如PPT文件的首頁(yè)顯示word圖標(biāo),表示該P(yáng)PT已包含配套word講稿。雙擊word圖標(biāo)可打開word文檔。
- 特殊限制:
部分文檔作品中含有的國(guó)旗、國(guó)徽等圖片,僅作為作品整體效果示例展示,禁止商用。設(shè)計(jì)者僅對(duì)作品中獨(dú)創(chuàng)性部分享有著作權(quán)。
- 關(guān) 鍵 詞:
- Java程序設(shè)計(jì)基礎(chǔ) Java 程序設(shè)計(jì) 基礎(chǔ) 10 輸入輸出 系統(tǒng)
鏈接地址:http://www.820124.com/p-11498750.html