什麼是流:流就是位元組序列的抽象概念,能被連續讀取資料的資料源和能被連續寫入資料的接收端就是流。
流的分類:
從流的目标類型分類:檔案流,網絡流,對象流等。
從流的方向分類:輸入流和輸出流
從流的内容分類:位元組流和字元流
從流的功能分類:節點流和包裝流(也有叫措置流,處理流,過濾流的)
檔案流就是基于計算機上存儲的檔案生成的流對象,網絡流就是基于網絡來傳送資訊的流對象,對象流也就是通過操作流的方式實作在計算機上存和讀取java實體對象的一種流類型。
輸入流就是能連續從其中讀取資料的對象,輸出流剛剛相反,就是能連續寫入資料到其中的對象。
位元組流操作的是最原始的位元組資料,而字元流實作了對位元組流操作的包裝,可以直接操作字元,原理也就是在底層讀取位元組的時候呢,并不會馬上傳回該位元組資料,而是在讀取到之後呢參照相應的字元編碼表來轉換成相應的字元,再傳回。unicode字元需要讀取兩個位元組,而utf-8字元有頭資訊是三個位元組。
節點流就是從特定方向讀取的流對象,也可以叫核心流,也就是說它是直接和原資料做互動。
包裝流隻是通過節點流做為輸入或者輸出,提供一些額外的功能,比如字元緩沖等。包裝流一般都接收一個節點流做為構造參數,它們一般也會實作同一個接口,之是以實作統一接口,是因為包裝類要保證擁有被包裝的核心流的所有的方法和功能。隻可以多而不可以少,而包裝流底層也是通過操作核心流來實作額外功能的。
ps: java io 體系所有子類的名稱的字尾名一般都是父類的名稱。
InputStream 是所有位元組輸入流的超類,它是個抽象類。并且所有過濾流的構造函數接收的類型也是它。
其中的方法也是所有輸出流類都有的方法:
available() 傳回目前未讀的位元組數,
close() 關閉流資源,
mark(int readlimit) 标記目前輸入流所在的位置,也就是目前輸入流讀取到的位置,readlimit 表示最大緩存多少個位元組,也就是記憶多少個位元組。當調用reset()方法的時候會重新定位到mark方法定位時的位置。InputStream 裡沒有實作這兩個方法,隻會抛出IOException。
markSupported() 測試此輸入流是否支援
mark
和
reset
方法。
read()方法,讀取單個位元組,以int類型傳回,是個抽象方法。
read(byte[]) 從輸入流中讀取一定數量的位元組,并将其存放到字元數組中。
read(byte[] b,int startIndex,int len) 從輸入流中的startIndex位置讀取len個位元組放到字元數組中,
reset()方法,将此流重新定位到最後一次對此輸入流調用
mark
方法時的位置。
skip(long n)方法, 跳過和丢棄此輸入流中資料的
n
個位元組。
FileInputStream : 從檔案系統中擷取某個檔案的輸入位元組。他主要用來讀取一些原始的字元,比如圖檔等,如果需要讀取的是文本字元,使用FileReader比較好。
構造函數有三個重載:File類型的執行個體,String 類型的檔案路徑名,還有FileDescriptor的執行個體(這個基本用不到)。
新增方法:
finalize() 确定在不引用該流對象時會關閉該流。
getChannel() 傳回該輸入流的檔案通道
getFD() 傳回相關的檔案系統FileDescriptor 對象。
該類未實作mark和reset方法。
用途:一般如果要建立一個檔案的輸入流都要用到它,非常常用的類。
ObjectInputStream和ObjectOutputStream這兩個包裝類,用于從底層輸入流中讀取對象類型的資料和将對象類型的資料寫入到底層輸入流。
ObjectInputStream與ObjectOutputStream類所讀寫的對象必須實作了Serializable接口。對象中的transient和static類型的成員變量不會被讀取和寫入。寫入對象和讀取對象的順序也應該是一樣的。
一般我們使用的也就是readObject()和writerObject()功能,因為實作了DataInput和DataOutput接口,他們也可以讀寫基本資料類型的資料,也可以讀寫byte類型資料。還有一些其他方法,感覺現在都用不到,等用得到的時候再慢慢研究吧。
用途:要序列化對象和反序列化對象時就要用到這兩個類了,還有就是在網絡中傳輸對象也要用到它們。
PipedInputStream和PipedOutputStream 用于在應用程式裡建立管道通信,比如一個線程和另外一個線程之間的通信,即一個線程在 PipedInputStream裡讀取資料 ,一個線程在往PipedOutputStream 裡寫入資料。
PipedInputStream構造函數有4個參數的重載:無參,指定int類型管道大小,PipedOutputStream 執行個體的,PipedOutputStream 執行個體加管道大小。PipedOutputStream 的構造函數參數隻有兩個,一個是無參的,一個是PipedInputStream的執行個體。
PipedInputStream裡的主要方法:
connect()方法:不管是PipedOutputStream 還是PipedInputStream都有這個方法,這是連接配接這個管道的方法。
receive(int byte) 方法:接收位元組,一般是給PipedOutputStream 調用的,讓它寫入位元組。
read() 方法, 傳回單個位元組
read(byte[] ,int ,int ) 讀取指定長度的位元組到數組中
PipedOutputStream 裡的主要方法:
connect()方法:連接配接管道
flush()方法:重新整理緩存區
write(byte[] b,int off, int len):将
len
位元組從初始偏移量為
off
的指定 byte 數組寫入該管道輸出流。
wirte(int b) : 将指定的byte資料寫入到輸出流中。
用途:在多個線程之間需要傳遞流資訊的時候。
SequenceInputStream:表示輸入流的邏輯串聯,意思就是可以将多個輸入流合并在一起,就差不多是存儲流的容器。但是可以把它們當作一個流對象來做一些操作,沒有對應的輸出流對象。
構造方法有兩個:一個是需要傳入一個實作了Enumeration 接口的對象,還有一個是須傳遞兩個InputStream接口的執行個體。
方法就是四個:available() ,read(), read(byte[],int ,int), clase();
需要注意的是它并不會把所有流對象集都完全合并成一個流對象,隻是相當于一個流的集合,一個一個的讀取。直到讀完所有流對象為止。
用途:當需要把多個輸出流對象合并在一起操作的時候。
FilterInputStream : 所有輸入流包裝類的父類,如果需要定義自己的輸出流包裝類,也需要繼承這個類。他的構造函數隻接受一個InputStream的執行個體。要包裝的也是那個執行個體。裡面的方法覆寫了部分InputStream的方法,但是沒有新增方法。
用途:隻有當需要自定義一個輸出流包裝類的時候才繼承它,一般不會直接使用它。
DataInputStream : FilterInputStream 的 子類,實作了DataInput接口,進而有了能在輸入流當中直接讀取java基本類型資料的能力。比如readBoolean(),readDouble(),readChar()等等。
用途:當需要在輸入流當中直接讀取java 基本資料類型的時候使用。
BufferedInputStream :FilterInputStream 的 子類,為其他輸入流對象提供記憶體緩沖數組,實作了mark和reset方法的功能。為了更好的效率,建議所有的輸出流對象都用此類來包裝。
構造函數有兩個:一個是傳遞一個InputStream的執行個體,另一個在這個基礎上多加了個緩存區大小(int)。此類沒有多增加方法,而是多了個緩存區而已。
用途:當需要給輸入流建立一個記憶體緩存區時使用,這樣可以提高讀資料的效率。
LineNumberInputStream : FilterInputStream 的 子類,可以擷取目前的行号或設定目前行号,已過時。已經被LineNumberReader替代。
用途:擷取目前輸入流的行數和設定行數。
PushbackInputStream : FilterInputStream 的 子類,可以将目前讀取的位元組資料推回到緩存區,一般用不到的。
用途:未知。
ByteArrayInputStream :建立一個記憶體緩存區,允許程式像操作流一樣來操作這個緩存區。
構造函數有兩個:一個是傳遞一個byte[]數組的參數來做為其緩沖區的數組,另一個是指定了這個緩沖數組的開始位置和截取個數。該類實作了mark和reset功能,沒有新增加方法。
用途:因為需要接收一個位元組數組做為自己的緩沖區,是以可以應用在一些已經存在位元組數組,但是讀取這個位元組數組的方法要和讀取流的方式一樣的情況下。
StringBufferInputStream 已經過時,由StringReader代
替了。