IO 輸入與輸出(3) -- 節點流之一InputStream和OutputStream

節點流需要掌握以下知識:

  • 理解流的概念
  • InputStreamOutputStream
  • FileInputStreamFileOutputStream
  • ReaderWriter
  •  PipedInputStreamPipedOutputStream
  • ByteArrayInputStreamByteArrayOutputStream

 

流是字節序列的抽象概念,例如文件、輸入輸出設備、網絡、內存等傳輸的數據序列都可以理解爲流,流提供了一種由統一的方式從各種輸入輸出設備中讀取和寫入字節數據的方法。

 

這裏一定要注意理解流和文件的差異:

 

   1.文件是數據的靜態存儲形式,而流是指數據傳輸時的形態。文件是一些具有永久存儲及特定順序的字節組成的一個有序的具有名稱的一些數據的集合。而流提供了一種向IO設備寫入字節和從IO設備中讀取字節的方式。

      2.文件只是流可操作的IO設備之一,除了文件流,還有網絡流,內存流,磁帶流等等。

 

數據流是一串連續傳輸的數據的集合,就像水管裏的水流一樣,在水管的一端一點一點的供水,而在水管的另一端看到的是一股連續不斷的水流,用於寫入數據的程序可以一段接一段的向數據流管道中寫入數據,這些數據段按先後順序形成一個長的數據流,對於讀取數據的程序來說,它看不到數據流在寫入時的分段,它每次可以讀取其中任意長度的數據,但只能先讀取前面的數據後再讀取後面的數據,不管數據是被分成多少次寫入還是做爲一個整體一次寫入,讀取的效果都應該是完全一樣的。

 

java中提供了衆多對流操作的類,通過這些流類應用程序可以方便的從各種IO設備中讀取和向IO設備寫入各種類型的數據。java的流分爲兩個大類:節點流類和過濾流類(也叫處理流類)。用於直接操作設備所對應的類叫節點類,節點流類所對應的IO源或者目標稱爲流節點,比如用一個類和某個文件或者網絡直接相關聯,那麼這個類就叫做節點流類,那麼這個文件或者這個網絡就叫做流的節點。程序也可以通過一個間接的流類去調用節點流類,以達到更加靈活的讀寫各種類型的數據,比如要通過網絡傳輸對象,我們就設計一種對象流的類,它可以把對象寫入到網絡當中去。那麼這個類實際上是調用底層的網絡流類。

 

首先我們先看一下InputStreamOutputStream

 

InputStream:程序可以從中連續讀取字節的對象叫輸入流,在java中用InputStream類來描述所有輸入流的抽象概念。InputStream類是一個抽象類,它沒有具體的對應到流設備,而是描述了所有流設備的共性。對應的網絡,管道,內存,文件等具體IO設備的那些流類都是InputStream的子類,例如之後還會介紹到的FileInputStream類。

 

InputStream有以下方法:

    a)         int read(): 從輸入流中讀取一個字節的內容,並且把這個字節的內容以整數的方式返回。如果碰到這個流的結束,返回值就是-1,如果流沒有結束而且暫時還沒有數據可讀,read()就會阻塞運行程序的執行過程,直到流中有新的數據可讀。

 

    b)         int read(byte[] b): 用於從輸入流中讀取一定數量的字節,並將其存儲在緩衝區數組 b 中,最多讀取的字節長度就是字節數組的長度,由於流中不一定有很多個數的字節可讀,那麼實際上它讀取的個數以read()的返回值爲準。

 

如果 b 的長度爲 0,則不讀取任何字節並返回 0;否則,嘗試讀取至少一個字節。如果因爲流位於文件末尾而沒有可用的字節,則返回值 -1;否則,至少讀取一個字節並將其存儲在 b 中。

 

將讀取的第一個字節存儲在元素 b[0] 中,下一個存儲在 b[1] 中,依次類推。讀取的字節數最多等於 b 的長度。設 k 爲實際讀取的字節數;這些字節將存儲在 b[0] b[k-1] 的元素中,不影響 b[k] b[b.length-1] 的元素。

(以上內容摘自JDK文檔)

 

    c)         read(byte[] b, int off, int len): 將輸入流中最多 len 個數據字節讀入 byte 數組中,從數組的下標off開始讀入

 

    d)         long skip(long n): 跳過輸入流中的n個字節,並返回實際跳過的字節數,一般用於包裝類當中。

 

    e)         int available(): 返回當前輸入流中可讀的字節數,檢測流中確實有數據可讀的時候再去調用read(),這樣就可以避免程序發生阻塞,如果程序要不停的實時的從流中讀取數據,每次都要用available()來檢查一下。這樣就會消耗較多的CPU資源,還不如在一個單獨的線程中直接循環的調用read(),當流中沒有數據,read()就會阻塞,這樣幾乎不佔用CPU資源。

 

    f)          void mark(int readlimit): 用於在輸入流當中建立一個標記,它接受一個參數,意思是從這個標記的開始最多還能夠讀取多少個字節,它也是用於包裝類的方法。

 

    g)         void reset(): 它和mark()方法配合使用,當在A這個地方做完標記以後,接着讀取幾個字節,到B以後再調用reset(),下次再讀的話又從A的地方開始讀取數據,就是讓指針回到以前做的標記處。

 

    h)         boolean markSupported(): 返回當前的流對象是否支持mark()reset()操作。

 

    i)           void close(): 用於所有流操作以後關閉。

 

OutputStream:程序可以向其中連續寫入字節的對象叫輸出流,在java中用OutputStream類來描述所有輸出流的抽象概念。它也是抽象類,也只是描述了輸出時的一些共性。

OutputStream
有以下方法:

 

    a)         void write(int b): 將一個整數當中的最低一個字節(整數是4個字節)內容寫到輸出流中,最高字節部分被捨棄。

 

    b)         write(byte[] b): b.length 個字節從指定的 byte 數組寫入輸出流。

 

    c)         write(byte[] b, int off, int len): 將指定 byte 數組中從偏移量 off 開始的 len 個字節寫入輸出流。

 

    d)         void flush(): 用於將內存緩衝區中的內容徹底的清空並且輸出到IO設備當中。

 

    e)         void close(): 關閉輸出流對象

 

版權聲明: 原創作品,允許轉載,轉載時請務必以超鏈接形式標明文章 原始出處 、作者信息和本聲明。否則將追究法律責任。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章