Java IO 流的總結
Java IO 總結圖
我們可以看到 IO流 分爲字符流和字節流
字節流:表示字節輸入輸出流
字符流:表示字符輸入輸出流
Java中的字節流處理的最基本單位爲單個字節,它通常用來處理二進制數據。
Java中的字符流處理的最基本的單元是Unicode碼元,它通常用來處理文本數據。
下面具體說一下字符流與字節流
字節流
字節流的基類分別是 輸入流: InputStream 和輸出流: OutputStream
繼承自InputStream派生的類都含有名爲read的方法,用於讀取單個字節或字節數組。
繼承自OuputStream派生的類都含有名爲write的方法,用於寫入單個字節或字節數組。
InputStream
1, InputStream的作用
InputStream 的作用是用來表示那些從不同數據源產生輸入的類,而最終結果就是通過read方法獲得數據源的內容,從數據源中讀出的內容用int或byte[]來表示.
2, InputStream的重要方法
- read() : 返回輸入流的下一個字節(next byte),如果已經到達輸入流的末尾,那麼返回-1
- read(byte b[]) 讀取b.length長度的字節,存入到b中,如果已經到達末尾返回-1,否則返回成功寫入到b中的字節數。
- read(byte b[], int off, int len) 取下len長度的字節,如果len爲0,那麼返回0,否則返回實際讀入的字節數,讀入的第一個字節存放在數據b[off]中,如果沒有可讀的,那麼返回-1。
- skip(long n) 跳過,並丟棄掉n個字節,其最大值爲2048。
PS: 四個方法中比較常用的 是 read(byte b[], int off, int len) 方法.
3, InputStream的具體實現類總結分析(比較常用到的)
1, ByteArrayInputStream(內存輸入流)
它接收byte[]作爲構造函數的參數,我們調用read方法時,就是從byte[]數組裏,讀取字節。
它共有兩個構造函數(主要接受 byte數組來進行讀取)
2, FileInputStream(文件輸入流)
支持提供文件名、File和FileDescription作爲構造函數的參數,它的read調用的是底層的native方法。
jdk中有三個構造函數, android的sdk中該類有四個構造函數, 但是本質上都是一樣的(主要用來包裹文件)
第一個構造函數 String 類型的 FileName(文件路徑) ,然後會把String抓換成一個File調用第二個構造函數
`public FileInputStream(String name) throws FileNotFoundException {
this(name != null ? new File(name) : null);
}`
第三個構造函數 直接傳入一個 FileDescriptor 對象,和第二個構造函數的區別問:
如果傳入 File 則會 new 一個 FileDescriptor ,如果傳入 FileDescriptor 則會直接使用這個 對象.
3, PipedInputStream(交換輸入流)
通過通信管道來交換數據,如果兩個線程希望進行數據的傳輸,那麼它們一個創建管道輸出流,另一個創建管道輸入流,它必須要和一個PipedOutputStream相連接。
它共有四個構造函數
這四個構造函數可以分爲兩組,
`public PipedInputStream(PipedOutputStream src) throws IOException {
this(src, DEFAULT_PIPE_SIZE);
}`
`public PipedInputStream() {
initPipe(DEFAULT_PIPE_SIZE);
}`
這兩組的區別是 如果傳入一個 PipedOutputStream 會多一個和 PipedOutputStream 連接的方法來建立管道.
4, SequenceInputStream(合併輸入流)
將多個InputStream連接在一起,一個讀完後就完畢,並讀下一個,它接收兩個InputStream對象或者一個容納InputStream對象的容器Enumeration。
它共有兩個構造函數
這兩個構造函數很清晰, 一個接收兩個流,一個接收多個流,它們最終會合併成一個流.
5, ObjectInputStream(對象輸入流)
和一個InputStream相關聯,源數據都是來自於這個InputStream ,主要用於對象進行反序列化, 即從一個序列化的文件中讀取數據變成對象(主要用於序列化和反序列化)
它有兩個構造函數, 其中一個 是 protected 修飾的, 就不說了,說一下 對外公佈的 構造函數
`public ObjectInputStream(InputStream in) throws IOException {
verifySubclass();
bin = new BlockDataInputStream(in);
handles = new HandleTable(10);
vlist = new ValidationList();
enableOverride = false;
readStreamHeader();
bin.setBlockDataMode(true);
}`
很明顯這個構造函數是用來包裹一個 InputStream 主要用來進行反序列化的.
5, FilterInputStream
`protected FilterInputStream(InputStream in) {
this.in = in;
}`
共1個構造函數 , 並且是 protected的類型, 不能創建對象
這個類很特殊,前面的InputStream子類都是傳入一個數據源(Pipe/byte[]/File)等等,然後通過重寫read方法從數據源中讀取數據,而FilterInputStream則是將InputStream組合在內部,它調用in去執行InputStream定義的抽象方法,也就是說它不會改變組合在內部的InputStream所對應的數據源。
另外,它還新增了一些方法,這些方法底層還是調用了read方法,但是它封裝了一些別的操作,比如DataInputStream中的readInt,它調用in連續讀取了四次,然後拼成一個int型返回給調用者,之所以採用組合,而不是繼承,目的是將(把二進制流轉換成別的格式)和(從某個數據源中讀出字節流)這兩個操作獨立開來,讓它們可以隨意地組合。
其下有三個類: BufferedInputStream(緩存流 , 常用) ; DataInputStream(不常用) ; PushbackInputStream(不常用)
- BufferedInputStream
有兩個構造函數
接受一個 InputStream , 來進行緩存從而進行有效率的讀取和寫入.
6, 其他
還有一個 LineNumberInputStream extends FilterInputStream 的LineNumberInputStream 數字流
和一個 StringBufferInputStream extends InputStream 的StringBufferInputStream 字符串緩存流
這兩個流已經被棄用了,不需要考慮
InputStream 到這裏就基本完畢了, 後面是 OutPutStream ,它和InputStream是對應的篇幅較少
OuputStream
OuputStream的作用
它決定了輸出要去往的目標,和InputStream類似,也是一個抽象類,它的子類代表了輸出所要去往的目標,我們主要關注的是write方法,前兩個write方法最終都是調用了抽象的write(int oneByte)方法,最終怎麼寫入是由子類實現的。
OutputStream的具體實現類
1, ByteArrayOutputStream(兩個構造函數)
在ByteArrayOutputStream的內部,有一個可變長的byte[]數組,當我們調用write方法時,就是向這個數組中寫入數據,它還提供了toByteArray/toString方法,來獲得當前內部byte[]數組中的內容。
2, FileOutputStream(五個構造函數, 主要增加一個boolean類型的值,用來標識 是否是在文件後面添加要輸出的內容,如果爲false , 則會把文件中的數據先清空在存入, 否則直接在文件的末尾進行添加寫入)
它和 FileInputStream 類似,只不過寫入的終點換成了所打開的文件。
3, PipedOutputStream(兩個構造函數)
和PipedInputStream相關聯。用於建立 通信管道來交換數據
4, ObjectOutputStream(兩個構造函數, public 的只有一個構造函數, 傳入一個OutPutStream)
和ObjectInputStream類似,只不過它內部組合的是一個OutputStream,當調用writeObject(Object object)方法時,其實是先將Object進行反序列化轉換爲byte,再輸出到OuputStream所指向的目的地,主要用來對 object 進行序列化。
5, FilterOutputStream
它的思想和FilterInputStream類似,都是在內部組合了一個OuputStream,FilterOutputStream提供了寫入int/long/short的write重載函數,當我們調用這些函數之後,FilterOutputStream最終會通過內部的OuputStream向它所指向的目的地寫入字節。
其下有三個類: BufferedOutputStream(緩存流 , 常用) ; DataOutputStream(不常用) ; PrintStream(打印流 , 常用 ,10個構造函數, 主要用於包裹OutputStream和File)
- BufferedOutputStream,用來進行緩存進行更快速的 讀取
- PrintStream,用來更加方便的輸出
6, 注意
沒有什麼勞什子的 SequenceOutputStream(只能合併, 而不能拆分…話說怎麼拆啊 ⊙﹏⊙)
OutputStream 到這裏也基本完畢了, 後面是 字符輸入輸出流 ,內容不多
字符流: 主要用於文檔的處理
Reader字符輸入流
其實現類有
1, BufferReader
緩存流, 兩個構造類, 主要用於包裹一個 Reader , 可以使用特定的方法 readLine() 直接一行一行的讀取,這個類是 1.1加上去的, 也就是說 1.0的時候是沒有這個 Reader的緩存字符流的
`public BufferedReader(Reader in) {
this(in, defaultCharBufferSize);
}`
`public BufferedReader(Reader in, int sz) {
super(in);
if (sz <= 0)
throw new IllegalArgumentException("Buffer size <= 0");
this.in = in;
cb = new char[sz];
nextChar = nChars = 0;
}`
2, InputStreamReader
轉換流, 四個構造函數, 主要用於 將流從 字節流轉換爲 字符流, 這個就是傳說中的字節流和字符流連接的橋樑O__O “…
至於爲什麼, 因爲 在Reader的所有實現類中只有它 可以接收一個 字節流 並處理, 所以它是 橋樑…
3, 其他實現類(個人感覺不常用)
1, StringReader
繼承自Reader , 只有一個構造函數 ,public StringReader(String s) ,用於讀取字符串, 功能叫少, 所以不常用
2, PipedReader
繼承自Reader , 有四個構造函數 , 通信管道來交換數據 , 主要用來包裹PipedWriter 來創建一個通道 ,不常用
3, CharArrayReader
繼承自Reader , 有兩個構造函數 , 用於讀取 字符列表
4, FilterReader
繼承自Reader , 一個構造函數(還不對外公佈) , 用於包裹一個Reader
` protected FilterReader(Reader in) {
super(in);
this.in = in;
}`
5, PushbackReader
繼承自FilterReader , 兩個構造函數 , 用於包裹一個Reader , 不常用
`public PushbackReader(Reader in) {
this(in, 1);
}`
`public PushbackReader(Reader in, int size) {
super(in);
if (size <= 0) {
throw new IllegalArgumentException("size <= 0");
}
this.buf = new char[size];
this.pos = size;
}`
Writer字符輸出流
其實現類有
1, BufferWriter
緩存流, 兩個構造類, 用於包裹一個Writer,對應於 BufferReader
2, OutPutStreamWriter(橋樑..)
轉換流, 四個構造函數 ,繼承自Writer , 包裹OutputStream, 其他類似 InputStreamReader同時FileWriter繼承自OutputStreamWriter , 一個構造函數 , 用於包裹 Writer
3, PrintWriter
打印流 , 9個構造函數 其中:
兩個用於包裹Writer public PrintWriter(Writer out,boolean autoFlush);
兩個用於包裹OutputStream , public PrintWriter(OutputStream out, boolean autoFlush);
五個用於包裹一個File 用來進行文件輸出
4, 其他實現類(個人感覺不常用)
1, StringWriter
繼承自Writer,兩個構造函數
2, PipedWriter
繼承自Writer , 兩個構造函數
3, CharArrayWriter
繼承自Writer , 兩個構造函數
4, FilterWriter
繼承自Writer ,兩個構造函數
OVER
累了…..
繼續努力