【正文】
《 Java程序設(shè)計之網(wǎng)絡(luò)編程 》 計算機學(xué)院 教學(xué)課件 第 9章 輸入輸出處理 主要內(nèi)容 I/O流的概念和劃分 文件的操作 字節(jié)流處理 字符流處理 串行化 I/O流的概念和劃分 ? 數(shù)據(jù)流( Stream)是一組有順序的、有起點和終點的字節(jié)集合,是對輸入和輸出的總稱和抽象。 ? Java程序通過流來完成輸入 /輸出。流通過 Java的輸入 /輸出系統(tǒng)與 物理設(shè)備 鏈接。 數(shù)據(jù)源 Data Source 程序 program 數(shù)據(jù)接收器 Data Sink Stream: 流 ? Java程序通過流來完成輸入 /輸出。流通過 Java的輸入 /輸出系統(tǒng)與物理設(shè)備連接。盡管與它們鏈接的物理設(shè)備不盡相同,所有流的行為具有同樣的方式。這樣,相同的輸入 /輸出類和方法適用于所有類型的外部設(shè)備。這意味著一個輸入流能夠抽象多種不同類型的輸入:從磁盤文件,從鍵盤或從網(wǎng)絡(luò)套接字。同樣,一個輸出流可以輸出到控制臺,磁盤文件或相連的網(wǎng)絡(luò)。流是處理輸入 /輸出的一個簡便的方法。 ? Java 2 定義了兩種類型的流:字節(jié)類和字符類。字節(jié)流( byte stream)為處理字節(jié)的輸入和輸出提供了方便的方法。例如使用字節(jié)流讀取或書寫二進制數(shù)據(jù)。字符流( character stream)為字符的輸入和輸出處理提供了方便。它們采用了統(tǒng)一的編碼標準,因而可以國際化。在某些場合,字符流比字節(jié)流更有效。 ? 需要聲明:在最底層,所有的輸入 /輸出都是字節(jié)形式的?;谧址牧髦粸樘幚碜址峁┓奖阌行У姆椒ā? Java流的劃分 ? 字節(jié)流類 ? 處理字節(jié)的輸入和輸出提供了方便的方法 ? 字符流類 ? 為字符的輸入和輸出處理提供了方便 ? 讀寫數(shù)據(jù)的單位不同 ? 最主要的是 Read() 和 Write() 方法 ? 每個流的特點 InputStream ? 1. int read() 從輸入流中讀取下一個字節(jié),返回范圍在 0到 255之間的一個整數(shù),該方法的屬性為 abstract,必須為子類所實現(xiàn)。 ? 2. int read(byte []) 從輸入流中讀取長度為 b. 1ength的數(shù)據(jù),寫入字節(jié)數(shù)組 b,并返回讀取的字節(jié)數(shù)。 ? 3. int read(byte[], int off,int len) 從輸入流中讀取長度為 len的數(shù)據(jù),寫入字節(jié)數(shù)組 b中從索引 off開始的位置,并返回讀取的字節(jié)數(shù)。 對于以上方法,如果到達流的末尾位置,則返回 1表明流的結(jié)束。 這三個方法提供對輸入管道數(shù)據(jù)的存取。簡單讀方法返回一個 int值,它包含從流里讀出的一個字節(jié)或者 1,其中后者表明文件結(jié)束。其它兩種方法將數(shù)據(jù)讀入到字節(jié)數(shù)組中,并返回所讀的字節(jié)數(shù)。 第三個方法中的兩個 int參數(shù)指定了所要填入的數(shù)組的子范圍。 ? 4. void close() 你完成流操作之后,就關(guān)閉這個流。如果你有一個流所組成的棧,使用過濾器流,就關(guān)閉棧頂部的流。這個關(guān)閉操作會關(guān)閉其余的 流。 ? 5. int available() 這個方法報告立刻可以從流中讀取的字節(jié)數(shù)。在這個調(diào)用之后的實際讀操作可能返回更多的字節(jié)數(shù)。 ? 6. skip(long) 這個方法丟棄了流中指定數(shù)目的字符。 ? 7. boolean markSupported() 確定輸入流是否支持方法 mark()和 reset()。 ? 8. void mark(int) 在輸入流的當前讀取位置作標記。從該位置開始讀取 readlimit所指定的數(shù)據(jù)后,標記失 效。 ? 9. void reset() 重置輸入流的讀取位置為方法 mark()所標記的位置。 如果流支持 “ 回放 ” 操作,則這些方法可以用來完成這個操作。如果 mark()和 reset()方法可以在特定的流上操作,則 markSupported()方法將返回 true。mark(int)方法用來指明應(yīng)當標記流的當前點和分配一個足夠大的緩沖區(qū),它最少可以容納參數(shù)所指定數(shù)量的字符。在隨后的 read()操作完成之后,調(diào)用 reset()方法來返回你標記的輸入點。 從以上方法中可以看到, InputStream中主要提供了對數(shù)據(jù)讀取的基本支持,其中的方法 通常都需要在子類中被重寫,以提高效率或是適合于特定流的需要。 OutputStream ? 1. void write(int) 將指定的字節(jié) b寫入輸出流。該方法的屬性為 abstract,必須為子類所實現(xiàn)。 注意:參數(shù)中的 b為 int類型,如果 b的值大于 255,則只輸出它的低位字節(jié)所表示的值。 ? 2. void write(byte b[]) 把字節(jié)數(shù)組 b中的 。 ? 3. void write(byte b[], int off, int len) 把字節(jié)數(shù)組 b中從索引 off開始的 len個字節(jié)寫入輸出流。 這些方法寫輸出流。和輸入一樣,總是嘗試以實際最大的塊進行寫操作。 ? 4. void close() 當你完成寫操作后,就關(guān)閉輸出流。如果你有一個流所組成的棧,就關(guān)閉棧頂部的流。這個關(guān)閉操作會關(guān)閉其余的流。 ? 5. void flush() 有時一個輸出流在積累了若干次之后才進行真正的寫操作。 flush( )方法允許你強制執(zhí)行寫操作。 ? FileInputStream和 FileOutputStream ? 這些類是結(jié)點流,而且正如這個名字所暗示的那樣,它們使用磁盤文件。這些類的構(gòu)造函數(shù)允許你指定它們所連接的文件。要構(gòu)造一個 FileInputStream,所關(guān)聯(lián)的文件必須存在而且是可讀的。如果你要構(gòu)造一個FileOutputStream而輸出文件已經(jīng)存在,則它將被覆蓋。 FileInputStream infile =new FileInputStream()。 FileOutputStream outfile =new FileOutputStream()。 ()。 ()。 下面舉例: ? BufferInputStream和 BufferOutputStream ? 這些是過濾器流,它們可以提高 I/O操作的效率。 BufferInputStream bi=new BufferInputStream(infile)。 BufferOutputStream bo=new BufferOutputStream(outfile)。 ()。 ? DataInputStream和 DataOutputStream 一個類實現(xiàn)接口 Datalnput和 DataOutput中定義的方法后,就可以用與機器無關(guān)的格式讀 /寫 Java的基本類型數(shù)據(jù)。類DataInputStream、 DataOutputStream和 RandomAccessFile分別實現(xiàn)了這兩個接口。這些過濾器通過流來讀寫 Java基本類。例如: ? DataInputStream方法 byte readByte() long readLong() double readDouble() DataOutputStream方法 void writeByte(byte) void writeLong(long) void writeDouble(double) ? 注意 DataInputStream和 DataOutputStream的方法是成對的。 ? 這些流都有讀寫字符串的方法,但不應(yīng)當使用這些方法。它們已經(jīng)被后面所討論的讀者和作者所取代。 ? PipedInputStream和 PipedOutputStream ? 管道流用來在線程間進行通信。一個線程的PipedInputStream對象從另一個線程的PipedOutputStream對象讀取輸入。要使管道流有用,必須有一個輸入方和一個輸出方。 例 91: 下面的程序?qū)崿F(xiàn)文件內(nèi)容的顯示。 import .*。 class Display{ public static void main(String args[])throws FileNotFoundException,IOException{ FileInputStream fis=new FileInputStream(“text”)。 BufferedInputStream bfis=new BufferedInputStream(fis)。 int b。 while(b=())!=1{ (b)。 } ()。 } } // class BufferedInputDemo { public static void main(String args[]) { BufferedInputStream bis = new BufferedInputStream( new FileInputStream(“”))。 int b。 try { while((b=())!=1) { ((char)b)。 } } catch(IOException e) { ()。 } }} Unicode ? Java技術(shù)使用 Unicode來表示字符串和字符,而且它提供了 16位版本的流,以便用類似的方法來處理字符。這些 16位版本的流稱為讀者Reader和作者 Writer。和流一樣,它們都在。 ? 最重要的是 InputStreamReader和OutputStreamWriter。這些類用來作為字節(jié)流與讀者和作者之間的接口。 ? 當你構(gòu)造一個 InputStreamReader或OutputStreamWriter時,轉(zhuǎn)換規(guī)則定義了 16位Unicode和其它平臺的特定表示之間的轉(zhuǎn)換。 Reader的例子 import .*。 public class CharInput { public static void main (String args[]) throws IOException { String s。 InputStreamReader ir。 BufferedReader in。 ir = new InputStreamReader()。 in = new BufferedReader(ir)。 while ((s = ()) != null) { (Read: + s)。 } } } 字節(jié)流輸入類 I n p u t S t r e a mF i l e I n p u t S t r e a mB y t e A r r a y I n p u t S t r e a mF i l t e r I n p u t S t r e a m P i p e d I n p u t S t r e a mO b j e c t I n p u t S t r e a mS e q u e n c e I n p u t S t r e a mB u f f e r e d I n p u t S t r e a mC i p h e r I n p u t S t r e a mD a t a I n p u t S t r e a mD i g e s t I n p u t S t r e a mP r o g r e s s M o n i t o r I n p u tS t r e a mP u s h b a c k I n p u t S t r e a mA u d i o I n p u t S t r e a m字節(jié)輸出類 O u t p u t S t r e a mF i l e O u t p u t S t r e a mB y t e A r r a y O u t p u t S t r e a m F i l t e r O u t p u t S t r e a mO b j e c t O u t p u t S t r e a mP i p e d O u t p u t S t r e a mB u f f e r e d O u t p u t S t r e a m C i p h e r O u t p u t S t r e a mD a t a O u t p u t S t r e a mD i g e s t O u t p u t S t r e a mP r i n t S t r e a m字符輸入流類 R e a d e rB u f f e r e d R e a d e rC h a r A r r a