Writer :BYSocket(泥沙磚瓦漿木匠) java
微 博:BYSocket git
豆 瓣:BYSocket github
FaceBook:BYSocket 數組
Twitter :BYSocket 緩存
InputStream是一個抽象類,即表示全部字節輸入流實現類的基類。它的做用就是抽象地表示全部從不一樣數據源產生輸入的類,例如常見的FileInputStream、FilterInputStream等。那些數據源呢?好比: 多線程
1) 字節數組(不表明String類,但能夠轉換) 分佈式
2) String對象 學習
3) 文件 測試
4) 一個其餘種類的流組成的序列化 (在分佈式系統中常見) spa
5) 管道(多線程環境中的數據源)
等等
兩者,注意它是屬於字節流部分,而不是字符流(java.io中Reader\Writer,下面會講到)。
FilterInputStream是爲各類InputStream實現類提供的「裝飾器模式」的基類。所以,能夠分爲原始的字節流和「裝飾」過的功能封裝字節流。
源碼以下:
/** * 全部字節輸入流實現類的基類 */ publicabstractclassSInputStream { // 緩存區字節數組最大值 privatestaticfinalintMAX_SKIP_BUFFER_SIZE = 2048; // 從輸入流中讀取數據的下一個字節,以int返回 publicabstractintread() throwsIOException; // 從輸入流中讀取數據的必定數量字節,並存儲在緩存數組b publicintread(byteb[]) throwsIOException { returnread(b, 0, b.length); } // 從輸入流中讀取數據最多len個字節,並存儲在緩存數組b publicintread(byteb[], intoff, intlen) throwsIOException { if(b == null) { thrownewNullPointerException(); } elseif(off < 0|| len < 0|| len > b.length - off) { thrownewIndexOutOfBoundsException(); } elseif(len == 0) { return0; } intc = read(); if(c == -1) { return-1; } b[off] = (byte)c; inti = 1; try{ for(; i < len ; i++) { c = read(); if(c == -1) { break; } b[off + i] = (byte)c; } } catch(IOException ee) { } returni; } // 跳過輸入流中數據的n個字節 publiclongskip(longn) throwsIOException { longremaining = n; intnr; if(n <= 0) { return0; } intsize = (int)Math.min(MAX_SKIP_BUFFER_SIZE, remaining); byte[] skipBuffer = newbyte[size]; while(remaining > 0) { nr = read(skipBuffer, 0, (int)Math.min(size, remaining)); if(nr < 0) { break; } remaining -= nr; } returnn - remaining; } // 返回下一個方法調用能不受阻塞地今後讀取(或者跳過)的估計字節數 publicintavailable() throwsIOException { return0; } // 關閉此輸入流,並釋放與其關聯的全部資源 publicvoidclose() throwsIOException {} // 在此輸出流中標記當前位置 publicsynchronizedvoidmark(intreadlimit) {} // 將此流從新定位到最後一次對此輸入流調用 mark 方法時的位置。 publicsynchronizedvoidreset() throwsIOException { thrownewIOException("mark/reset not supported"); } // 測試此輸入流是否支持 mark 和 reset 方法 publicbooleanmarkSupported() { returnfalse; } }
其中,InputStream下面三個read方法纔是核心方法:
public abstract int read()
抽象方法,沒有具體實現。由於子類必須實現此方法的一個實現。這就是輸入流的關鍵方法。
兩者,可見下面兩個read()方法都調用了這個方法子類的實現來完成功能的。
public int read(byteb[])
該方法是表示從輸入流中讀取數據的必定數量字節,並存儲在緩存字節數組b。其效果等同於調用了下面方法的實現:
read(b, 0, b.length)
若是b的長度爲 0,則不讀取任何字節並返回 0;不然,嘗試讀取至少 1 字節。若是由於流位於文件末尾而沒有可用的字節,則返回值 -1;不然,至少讀取一個字節並將其存儲在 b 中。
思考:這時候,怪不得不少時候, b != –1 或者 b != EOF
public int read(byteb[], intoff, intlen)
在輸入數據可用、檢測到流末尾或者拋出異常前,此方法一直阻塞。
該方法先進行校驗,而後校驗下個字節是否爲空。若是校驗經過後,
以下代碼:
int i = 1; try{ for(; i < len ; i++) { c = read(); if(c == -1) { break; } b[off + i] = (byte)c; } } catch(IOException ee) { }
將讀取的第一個字節存儲在元素 b[off] 中,下一個存儲在 b[off+1] 中,依次類推。讀取的字節數最多等於 len。設 k 爲實際讀取的字節數;這些字節將存儲在 b[off] 到 b[off+k-1] 的元素中,不影響 b[off+k] 到 b[off+len-1] 的元素。
由於有上面兩個read的實現,因此這裏InputStream設計爲抽象類。
1. InputSream 對應着 OutputStream
2. 看源碼是享受人家寫代碼中流露的How
3. 泥瓦匠學習的代碼都在github上(同步osc git),歡迎你們點star,提意見,一塊兒進步。地址:https://github.com/JeffLi1993