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()
|
abstract int |
read()
|
int |
read(byte[] b)
|
(返回值實際讀取多少值) int |
read(byte[] b, int off, int len)
|
void |
reset()
|
long |
skip(long n)
(幾乎不用) |
OutputStream
void |
close()
|
void |
flush()
|
void |
write(byte[] b)
|
void |
write(byte[] b, int off, int len)
|
abstract void |
write(int b)
|
對於flush和close
Close的關閉非常粗暴,close將直接將管道關閉,而flush將先把緩衝區的內容全部輸出,然後再用close纔是最好的選擇。
Reader
Reader與InputStream的區別在於後者兩個字節兩個字節的讀(中文字符佔兩個字節,若只一個字節一個字節的讀,只能讀半個)
abstract void |
close()
|
void |
mark(int readAheadLimit)
|
boolean |
markSupported()
|
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
append(char c)
|
|
append(CharSequence csq)
|
|
append(CharSequence csq, int start, int end)
|
|
abstract void |
close()
|
abstract void |
flush()
|
void |
write(char[] cbuf)
|
abstract void |
write(char[] cbuf, int off, int len)
|
void |
write(int c)
|
void |
|
void |
String中有可以將String變成字符數組的方法。
節點流類型
protected |
FilterInputStream(InputStream in)
|
int |
available()
|
void |
close()
|
void |
mark(int readlimit)
|
boolean |
markSupported()
|
int |
read()
|
int |
read(byte[] b)
|
int |
read(byte[] b, int off, int len)
|
void |
reset()
|
long |
skip(long 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中有將字節轉換爲字符的流,但沒有將字符轉換爲字節的(因爲內存中本來就是以字節形式儲存的)。
注意每種類的用途,區別,名稱,類別。