JDK源碼-InputStream系列

byte

了解InputStream前,我們先了解下byte.

  • byte存在的意義:
    byte,字節,java中一種基本類型.通常在讀取非文本文件(圖片,聲音,可執行文件,網絡通信的數據)需要通過字節數組來保存文件中的內容.
    一個byte占用了8個bit位,所以byte的取值范圍為-128到127.
    內存的最小單元是字節,Intel的X86的芯片內存地址是通過字節編的,指針可以指向的最小內存單元就是一個字節,16位的機器是兩個字節,32位的機器是四個字節.
  • byte的包裝類

byte的包裝類就是Byte,列舉一下常見方法

  • toString(byte b) //靜態的,調用了Integer.toString()
  • ByteCache() //不是很懂,也不是靜態方法啊
  • parseByte(String s) //超過范圍或者不是數字會報:NumberFormatException,調用了Integer.parseInt()
  • valueOf() //把括號里的參數變成Byte對象,超過范圍或者不是數字會報:NumberFormatException
  • byteValue() //返回Byte里的byte
  • shortValue() //返回short,代碼里加了強轉,平時不寫是隱式類型轉換,jvm實現的。
  • intValue(),longValue() //同上
  • floatValue(),doubleValue() //同上,但是不知道精度是否會丟失【TODO】
  • toString() //源碼里調用了Integer.toString,非靜態
  • hashCode() //返回這個類的hashCode
  • equals() //直接比byte了,也不用比hashCode了
  • compareTo(Byte anotherByte) //和另外一個Byte比較大小
  • compare(byte x, byte y) //靜態方法

InputStream

抽象架構圖

InputSteam是所有字節輸入流的實現類的基類.它封裝了流處理類的基本操作.

緩存區字節數組最大值
private static final int MAX_SKIP_BUFFER_SIZE = 2048;
從輸入流中讀取數據的下一個字節,返回int
public abstract int read() throws IOException;
從輸入流中讀取b.length大小的字節,并存儲到字節數組b.
public int read(byte b[]) throws IOException {
        return read(b, 0, b.length);
    }

該方法調用了抽象方法:read(),通過該方法獲取流中下一個元素.

public int read(byte b[], int off, int len) throws IOException {
        if (b == null) {
            throw new NullPointerException();
        } else if (off < 0 || len < 0 || len > b.length - off) {
            throw new IndexOutOfBoundsException();
        } else if (len == 0) {
            return 0;
        }

        int c = read();
        if (c == -1) {
            return -1;
        }
        b[off] = (byte)c;

        int i = 1;
        try {
            for (; i < len ; i++) {
                c = read();
                if (c == -1) {
                    break;
                }
                b[off + i] = (byte)c;
            }
        } catch (IOException e) {
        }
        return i;
    }

原始流處理器

接收一個Byte數組對象,或者一個FileDiscriptor對象,一個String對象,或者其他類型的流源對象.
主要一下四種:

ByteArrayInputStream
  • ByteArrayInputStream里的方法基本上都被synchronized關鍵字修飾,所以它是線程安全的.
  • ByteArrayInputStream底層是一個緩沖字節數組
/**
     * An array of bytes that was provided
     * by the creator of the stream. Elements <code>buf[0]</code>
     * through <code>buf[count-1]</code> are the
     * only bytes that can ever be read from the
     * stream;  element <code>buf[pos]</code> is
     * the next byte to be read.
     */
    protected byte buf[];
  • 一般情況下很少使用ByteArrayInputStream,它存在的意義一方面是擴展了InputStream基類,可以通過它賴操作字節數組,另一方面,相當于是其他所有流的一個中間狀態.,用來緩存其他流輸入的數據.
  • 關閉一個字節流是沒有意義的.
/**
     * Closing a <tt>ByteArrayInputStream</tt> has no effect. The methods in
     * this class can be called after the stream has been closed without
     * generating an <tt>IOException</tt>.
     */
    public void close() throws IOException {
    }
FileInputStream

先了解下一些相關類的實現:JDK源碼-File系列

  • FileInputStream用來操作文件流數據,通過構造函數可知,可以通過文件路徑,文件對象,文件描述符對象來創建文件輸入流對象.
public FileInputStream(String name) throws FileNotFoundException {
        this(name != null ? new File(name) : null);
    }

public FileInputStream(File file) throws FileNotFoundException {
        String name = (file != null ? file.getPath() : null);
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkRead(name);
        }
        if (name == null) {
            throw new NullPointerException();
        }
        if (file.isInvalid()) {
            throw new FileNotFoundException("Invalid file path");
        }
        fd = new FileDescriptor();
        fd.attach(this);
        path = name;
        open(name);
    }
public FileInputStream(FileDescriptor fdObj) {
        SecurityManager security = System.getSecurityManager();
        if (fdObj == null) {
            throw new NullPointerException();
        }
        if (security != null) {
            security.checkRead(fdObj);
        }
        fd = fdObj;
        path = null;

        /*
         * FileDescriptor is being shared by streams.
         * Register this stream with FileDescriptor tracker.
         */
        fd.attach(this);
    }
  • FileInputStream的讀取操作和打開文件的操作都是調用本地的native方法.
 /**
     * Opens the specified file for reading.
     * @param name the name of the file
     */
    private native void open0(String name) throws FileNotFoundException;

    // wrap native call to allow instrumentation
    /**
     * Opens the specified file for reading.
     * @param name the name of the file
     */
    private void open(String name) throws FileNotFoundException {
        open0(name);
    }

    /**
     * Reads a byte of data from this input stream. This method blocks
     * if no input is yet available.
     *
     * @return     the next byte of data, or <code>-1</code> if the end of the
     *             file is reached.
     * @exception  IOException  if an I/O error occurs.
     */
    public int read() throws IOException {
        return read0();
    }

    private native int read0() throws IOException;
PipedInputStream&PipedOutputStream

PipedInputStream與PipedOutputStream的設計,主要為了實現線程之間可以通過字節流來傳輸數據,來達到通信.

參考文章:Java流編程實例及代碼

StringBufferInputStream

StringBufferInputStream:將一個字符串緩沖區轉換為一個輸入流。接收一個String對象作為流的源。(JDK幫助文檔上說明:已過時。此類未能正確地將字符轉換為字節。從JDK1.1開始,從字符串創建流的首選方法是通過StringReader類進行創建。只有字符串中每個字符的低八位可以由此類使用。)

ObjectInputStream/ObjectOutputStream

詳見JDK源碼-InputStream系列之ObjectOutputStream/ObjectInputStream

鏈接流處理器

FilterInputStream
  • FilterInputStream主要用于包裝一些其他的基本數據的流對象.
  • 該類以及父類,子類的設計對應了裝飾者模式.通過FilterInputStream的代理,所有的子類都可以裝飾一個InputStream類型的對象.這樣,就能夠實現所有裝飾類之間的互相轉換了.
  • FilterInputStream實現了InputStream接口,同樣實現了流處理對象的那一套方法.
BufferedInputStream
  • 它存在的意義是給另外的輸入流添加功能,例如,提供“緩沖功能”以及支持“mark()標記”和“reset()重置方法”。
  • 它的底層實現是一個內部緩存數組.在讀取輸入流的時候,它會分批讀入到緩沖區,當緩沖區中的數據被讀完之后,輸入流會再次填充數據緩沖區.
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,622評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,716評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,746評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,991評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,706評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,036評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,029評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,203評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,725評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,451評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,677評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,161評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,857評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,266評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,606評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,407評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,643評論 2 380

推薦閱讀更多精彩內容

  • tags:io categories:總結 date: 2017-03-28 22:49:50 不僅僅在JAVA領...
    行徑行閱讀 2,199評論 0 3
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,738評論 18 399
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,836評論 18 139
  • 早上為兒子做好早餐送他上學,兒子給我講了昨天在學校發生的事情! 有個女同學交作業時找不到作業本了,她告訴老師:“老...
    繆璘夙閱讀 332評論 0 0
  • 鄧平1閱讀 149評論 0 0