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