java中把不同的輸入/輸出源(鍵盤、文件、網(wǎng)絡(luò)連接等)抽象表現(xiàn)為Stream(流).
java程序可以通過使用不同的流來訪問不同的輸入/輸出源.而Stream(流)可以直觀的理解為從數(shù)據(jù)的源(Source)到數(shù)據(jù)的接收(Sink)之間的這樣一段有序數(shù)據(jù).
ps. 注意此處是Stream(流) 并不是 那款常喝的運動飲料的Scream(尖叫) 也不是冰激凌的奶油 Cream
大家看以參照下圖,在腦海中想象一下,途中的水滴就是流中的數(shù)據(jù),他們共同組成了這段有序的數(shù)據(jù)(水:流)。

一、流的分類
1、按照流的方向(從程序運行所在的內(nèi)存的角度來劃分)
輸入流:只能從流中讀取數(shù)據(jù),不能向其寫出數(shù)據(jù).(基類 InputStream, Reader)
輸出流:只能向其寫出數(shù)據(jù),不能從中讀入數(shù)據(jù)(基類OutputStream,Writer)
2、按照操作的數(shù)據(jù)單元不同
字節(jié)流:操作的最小數(shù)據(jù)單元是字節(jié)(8 bit),主要以InputStream、OutputSteam為基類
字符流:操作的最小數(shù)據(jù)單元是字符(16bit),主要以Reader、Writer為基類
3、按照流的角色分
節(jié)點流:可以從/向一個特定的IO設(shè)備讀寫數(shù)據(jù)的流。這種流屬于一種Low level Stream.
這種流往往直接連接到實際(防盜連接:本文首發(fā)自http://m.survivalescaperooms.com/jilodream/ )的數(shù)據(jù)源,即和實際的輸入輸出節(jié)點直接連接.
處理流(包裝流):用于對已經(jīng)存在的流進行連接和封裝,通過封裝后的流來實現(xiàn)數(shù)據(jù)的讀寫功能。這種流往往成為高級流。
這種流通過對不同節(jié)點流的包裝,使得程序可以使用完全相同的輸入輸出代碼來訪問不同的數(shù)據(jù)源。
是一種典型的外觀模式。即不改變原有類的使用和繼承的情況。通過創(chuàng)建一個包裝對象,來包裹真實的數(shù)據(jù)。此處原有類的使用和繼承就是節(jié)點流。通過包裝流來包裹真實數(shù)據(jù),而擴展功能。
二、流的概念模型
流可以理解為:把輸入設(shè)備抽象成一個"水管",這個水管中的每個"水滴"依次排序,每一個水滴就可以理解為輸入輸出的單位(即前文中講到的字節(jié)和字符).這些水滴形成的一個有序序列就是流。
輸入流使用隱式的記錄指針來表示當(dāng)前正準(zhǔn)備從哪個水滴來開始讀取數(shù)據(jù)。每當(dāng)程序從 inputStream/Reader 中取出一個或多個"水滴"的時候,記錄指針就會自動向后移動。
輸出流的話可以理解為在一根已經(jīng)通向目標(biāo)的管道邊,程序一次把輸出的"水滴"防止到需要輸出的管道中。
這樣我們就能理解流除了在內(nèi)存中分配空間,還要占用操作系統(tǒng)的資源。
下面來看個例子
1 public class TempStreamModle 2 { 3 public static void main(String[] args) 4 { 5 PRintStream ps= null; 6 try 7 { 8 ps=new PrintStream(new FileOutputStream("out.txt"));// 創(chuàng)建輸出流 9 System.setOut(ps);//將輸出的流指定到ps流10 System.out.println("common String");11 System.out.println(new TempStreamModle());12 }13 catch(IOException ex)14 {15 //solve error16 }17 finally18 {19 if(ps!=null)20 {21 ps.close();22 }23 }24 }25 }
Java的GC 只能回收jvm中不使用的對象,對操作系統(tǒng)分配的其他資源無法進行回收。所以需要我們主動的調(diào)用close()
調(diào)用close()方法的好處是:
(1)保證流占用的物理資源可以被釋放
(2)將輸出流緩沖中的數(shù)據(jù)flush(沖洗)到物理節(jié)點里。相當(dāng)于主動執(zhí)行了flush()方法。
PS. Java在使用流時,一般都會有一個緩沖區(qū),按一種它認為比較高效的方法來發(fā)數(shù)據(jù):應(yīng)用程序每次IO都要和設(shè)備進行通信,效率很低,因此緩沖區(qū)為了提高效率,當(dāng)寫入設(shè)備時,會先寫入緩沖區(qū),等到緩沖區(qū)有足夠多的數(shù)據(jù)(防盜連接:本文首發(fā)自http://m.survivalescaperooms.com/jilodream/ )時,就整體寫入設(shè)備(注意繪制GUI界面時,也是使用此種思路來保證界面在繪制或者拖動時不發(fā)生閃動)。而flush()表示強制將緩沖區(qū)中的數(shù)據(jù)發(fā)送出去,不必等到緩沖區(qū)滿再執(zhí)行。所以如果在用流的時候,如果沒有用flush()這個方法,很多情況下會出現(xiàn)流的另外一側(cè)讀不到數(shù)據(jù)的問題,特別是在數(shù)據(jù)非常小的情況下。
這就相當(dāng)于旅游區(qū)的景點觀光車一樣,人滿才會發(fā)車(flush),但是當(dāng)下班時,無論最后一班車里有多少人,都會發(fā)最后一班車,而不會等到車滿(緩沖區(qū)滿)。

新聞熱點
疑難解答