Java筆記系列(基於馬士兵的課堂)(5)-IO

IO初步:(流)

概括:Java輸入輸入輸出流原理。Java流的分類。輸入輸出流類。常見的節點流和處理流。文件流。緩衝流。數據流。轉換流。Print流。Object流。

流:(即管道)<一端接着管道,一端接着數據源>java中對於數據的輸入輸如輸出操作以流的形式進行。對文件,對空間的訪問,讀取通過流的方式獲取不同種類的數據。程序通過標準的方法輸入或輸出程序。(在文件,信息中插入管道,使其可以流進去,或可以流出來這樣的管道就叫做流)<與水流的方式一模一樣>網絡連接,文件與文件之間,文件與程序之間,程序與程序之間都可以通過流(注意運輸的是二進制代碼,但有加強的管道可以將這些二進制代碼轉換成所對應的數據再運輸到別的程序文件裏)


流的分類:


上一章,可見接口可以組織成一個龐大的繼承體系,本章與上一章有相同點,也有不同點,本章對於流的體系組織是四個抽象類。

輸入流輸出流:

站在程序的角度上看是在輸入程序數據,還是在輸出程序(改變文件)

字符流字節流:

字節流是最原始的流,0101001(8位8位讀)字符流(兩個字節char)讀

節點流處理流:

節點流:直接將管道接通文件與程序。

處理流:在管道之上套着,對文件數據的傳輸起處理作用的叫處理流。(可以套許多層)<更高級>

(以Stream結尾的都是字節流)Reader(字符流)輸入流,writer(字符流)輸出流

InputStream

Buffer緩衝區可以減少讀寫的次數,減少對硬件的損傷,相當於一個小桶,一次性裝許多東西,一次性寫到硬盤,這樣的緩衝區可以使用字節數組完成。

 int

available()
          返回此輸入流下一個方法調用可以不受阻塞地從此輸入流讀取(或跳過)的估計字節數。

 void

close()
          關閉此輸入流並釋放與該流關聯的所有系統資源。

 void

mark(int readlimit)
          在此輸入流中標記當前的位置。

 boolean

markSupported()
          測試此輸入流是否支持 mark 和 reset 方法。

abstract  int

read()
          從輸入流中讀取數據的下一個字節。

 int

read(byte[] b)
          從輸入流中讀取一定數量的字節,並將其存儲在緩衝區數組 b 中。

(返回值實際讀取多少值) int

read(byte[] b, int off, int len)
          將輸入流中最多 len 個數據字節讀入 byte 數組。

 void

reset()
          將此流重新定位到最後一次對此輸入流調用 mark 方法時的位置。

 long

skip(long n) (幾乎不用)
          跳過和丟棄此輸入流中數據的 n 個字節。

OutputStream

 void

close()
          關閉此輸出流並釋放與此流有關的所有系統資源。

 void

flush()
          刷新此輸出流並強制寫出所有緩衝的輸出字節。

 void

write(byte[] b)
          將 b.length 個字節從指定的 byte 數組寫入此輸出流。

 void

write(byte[] b, int off, int len)
          將指定 byte 數組中從偏移量 off 開始的 len 個字節寫入此輸出流。

abstract  void

write(int b)
          將指定的字節寫入此輸出流。

對於flush和close

Close的關閉非常粗暴,close將直接將管道關閉,而flush將先把緩衝區的內容全部輸出,然後再用close纔是最好的選擇。

Reader

Reader與InputStream的區別在於後者兩個字節兩個字節的讀(中文字符佔兩個字節,若只一個字節一個字節的讀,只能讀半個)

abstract  void

close()
          關閉該流並釋放與之關聯的所有資源。

 void

mark(int readAheadLimit)
          標記流中的當前位置。

 boolean

markSupported()
          判斷此流是否支持 mark() 操作。

 int

read()
          讀取單個字符。

 int

read(char[] cbuf)
          將字符讀入數組。

abstract  int

read(char[] cbuf, int off, int len)
          將字符讀入數組的某一部分。

 int

read(CharBuffer target)
          試圖將字符讀入指定的字符緩衝區。

 boolean

ready()
          判斷是否準備讀取此流。

 void

reset()
          重置該流。

 long

skip(long n)
          跳過字符。

Writer

 Writer

append(char c)
          將指定字符添加到此 writer。

 Writer

append(CharSequence csq)
          將指定字符序列添加到此 writer。

 Writer

append(CharSequence csq, int start, int end)
          將指定字符序列的子序列添加到此 writer.Appendable。

abstract  void

close()
          關閉此流,但要先刷新它。

abstract  void

flush()
          刷新該流的緩衝。

 void

write(char[] cbuf)
          寫入字符數組。

abstract  void

write(char[] cbuf, int off, int len)
          寫入字符數組的某一部分。

 void

write(int c)
          寫入單個字符。

 void

write(String str)
          寫入字符串。

 void

write(String str, int off, int len)
          寫入字符串的某一部分。

String中有可以將String變成字符數組的方法。


節點流類型


protected

FilterInputStream(InputStream in)
          將參數 in 分配給字段 this.in,以便記住它供以後使用,通過這種方式創建一個 FilterInputStream。

 int

available()
          返回下一次對此輸入流調用的方法可以不受阻塞地從此輸入流讀取(或跳過)的估計剩餘字節數。

 void

close()
          關閉此輸入流並釋放與此流關聯的所有系統資源。

 void

mark(int readlimit)
          在輸入流中的當前位置上作標記。

 boolean

markSupported()
          測試此輸入流是否支持 mark 和 reset 方法。

 int

read()
          從此輸入流中讀取下一個數據字節。

 int

read(byte[] b)
          從此輸入流中將 byte.length 個字節的數據讀入一個 byte 數組中。

 int

read(byte[] b, int off, int len)
          從此輸入流中將 len 個字節的數據讀入一個 byte 數組中。

 void

reset()
          將此流重新定位到對此輸入流最後調用 mark 方法時的位置。

 long

skip(long n)
          跳過和丟棄此輸入流中數據的 n 個字節。

FileInputStream與FileOutputStream

見相應javaIO包中的練習

FileReader與FileWriter(與上述相同)

只不過顯示中文很好。(但還是有的文字符號顯示不了,因爲可能有的國家的語言需要更大的字節,java不能提供)

處理流:(包在別的流上的流)

類型


緩衝流(小桶):(BufferedReader,BufferedWriter)內存中的相應緩衝內存。

見TestBufferStream。

1310(asc碼中是回車,轉換成字符後就是個空格)

這是一種套在節點流上的處理流,使管道擁有緩衝區。、

BufferReader


注意文件的內容的讀寫是在內存中的執行,而並非在命令提示框內,也並非在

中有一個特別好的方法,readLIne()這個方法可以讀一行代碼(返回值是一個String)。

轉換流



轉換流可以把字節流轉換成字符流,將讀取的方式改變。InputStreamReader(轉換InputStream變成Reader)OutputStreamWriter(轉換OutputStream變成Writer)注意程序中的true,如果沒有這個true,這個命令將把這個文件的內容擦去,重新寫,而有了這個true之後,他將在文件後面繼續寫。

之前在寫的時候沒有選擇編碼,會使用當前系統默認的編碼(中文windows用的是gbk)

後來指定好了,編碼爲ISO08859_1.所以結果會打印兩邊。

這樣一來在字節管道外面加一層可以使其灌輸更快,直接字符串,不用再字符,或字符數組。

 

西歐文字,就是ISO9959_1,後來就纔出現了Unicode(16)

System.out對象是命令行代碼,System.in是InputStream類型(是一個子類),

System.in是在接收鍵盤的輸入。

管道接在鍵盤上,正準備讀鍵入內容(一個字符,一個字符的讀)。

BufferedReader可以讀一行,有readLine()方法。這個程序有三個參數。

這是一個輸入的參數知道輸入exit。

DataIn/OutputStram,即ByteArrayIn/OutputStream

ByteArrayIn/OutputStream是可以(以字節數組)傳輸數據的管道,而這不方便我們傳輸較大的數字,及一些基本數據類型,因爲基礎數據類型在傳輸時,需要先轉換成一個一個的字符串,再拆字符,轉換爲字節數組再傳進出,但如果我們直接套上數據流就不會這麼麻煩了,因爲數據流可以直接傳輸基礎數據類型(同時還可以計算這些數據類型的佔多少字節),注意這些基礎數據類型在寫的時候的順序,在讀的時候也要按順序,否則其會取類型的一部分進行強制轉換,發生數據丟失,溢出。同時這種方法還可以傳輸unicode編碼,注意Unicode(utf8)與UIcode(utf16)有區別,前者雖爲早期,但其佔空間較小,所以網落上一般使用這種Unicode編碼。

Print流(只有輸出沒有輸入)(基礎節點流)

PrintWriter和PrintStream(一個輸出字節,一個輸出字符)

二者重寫了Print方法,System中的out是一個靜態的,是PrintStream類型。

Print流可以用於輸出各種類型的數據,而且PrintWriter和PrintStream的輸出操作不會拋出異常。Print流有自動的flush功能,即緩存自動清除,每輸出一次,flush一次。

Out也可以通過setOut方法改變輸出位置(默認輸出在命令行窗口),System.out的輸出地方就變了(變成了文件,因爲out是PrintStream類型),分析管道程序,畫圖很重要。

第一個程序重寫了out,第二個程序可以將輸出管道在命令行窗口輸入地址,將該地址下的文件,用管道輸出到命令行窗口。

第三個程序是日誌程序,可以記錄程序員對程序的改動,操作。Java有專門的日誌api,日誌開發包。注意這裏文件可以不用flush,但需要close。Java.util.date封裝了當前的日期(裝的long的毫秒數可正可負),對於這個long類型的數有對其進行操作專門的類。對於程序三,其還可以記錄輸入命令的時間(可以用於聊天室的構建)

 

Object流(處理流 objectout/InputStream

用於直接將Object寫入或讀出,transient關鍵字。Serializable接口。Externalizable接口。

在new object的時候會有一些相關的版本號,指針之類的東西會被Object流一併寫入。

對於Serializable(可被序列化的)是標記性接口這是一個沒有方法的接口,編譯器會識別它,認爲他是可以序列化的。(如果想讓某個類的對象可以被序列化,一定要讓這個類實現Serializable)<這樣就可以直接將Object分解再組裝,不用一個一個的寫,讀>

Transient透明的:可以修飾成員變量,這個成員變量在序列化時可以不被序列化,這樣,這個值在讀的時候就是系統默認的值,爲0。

Externalizable(接口)外部化:實現externalizable接口(serializable的子接口)可以決定自己的對象是如何序列化的。控制自己對象的寫入寫出過程,但這時必須要重寫這個接口的兩個方法。

總結:

本章主要是管道的對接方法和使用,以及管道與管道之間的不同。主要是:字節流,字符流,節點流,處理流,輸入流,輸出流,總的還是幾個抽象類組織起的框架。Java中有將字節轉換爲字符的流,但沒有將字符轉換爲字節的(因爲內存中本來就是以字節形式儲存的)。

注意每種類的用途,區別,名稱,類別。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章