摘要:從應用流向目的地稱為輸出流,從目的地流向應用稱為輸入流。裝飾器模式裝飾器模式允許向一個現有的對象添加新的功能,同時又不改變其結構。以及家屬對于裝飾器模式的體現,也以此類推。
流概述
Java中,流是一種有序的字節序列,可以有任意的長度。從應用流向目的地稱為輸出流,從目的地流向應用稱為輸入流。
Java的流族譜Java的java.io包中囊括了整個流的家族,輸出流和輸入流的譜系如下所示:
InputStream和OutputStream分別是輸入輸出流的頂級抽象父類,只定義了一些抽象方法供子類實現。
在輸出流OutputStream中,如果你需要向一個輸出流寫入數據,可以調用void write(int b)方法,這個方法會將b的低八位寫入流中,高24位將會被自動忽略。如果想要批量寫入數據呢,那么可以調用void write(byte[] b) 方法將一個字節數組的內容全部寫入流中,同時還有void write(byte[] b, int off, int len)可以讓你指定從哪里寫入多少數據。
如果你希望你向流中寫入的數據能夠盡快地輸送到目的地,比如說文件,那么可以在寫入數據后,調用flush()方法將當前輸出流刷到操作系統層面的緩沖區中。不過需要注意的是,此方法并不保證數據立馬就能刷到實際的物理目的地(比如說存儲)。
使用完流后應該調用其close()方法將流關閉,流關閉時,將會先flush,后關閉。
在輸入流InputStream中,可以通過int read() 方法來從流中讀取一個字節,批量讀取字節可以通過int read(byte[] b)或者int read(byte[] b, int off, int len)來實現,這兩個方法的返回值為實際讀取到的字節數。如果需要重復讀取流中某段數據,可以在讀取之前先使用void mark(int readlimit)方法在當前位置做一個記號,之后通過void reset()方法返回到之前做標記的位置,不過在做這些標記操作之前,需要先通過boolean markSupported()方法來確定該流是否支持標記。如果對某些可預知的數據不感興趣,可以使用long skip(long n)來調過一些流中的一些數據。
使用完流,無論是輸入還是輸出流,都要調用其close()方法對其進行關閉。
裝飾器模式裝飾器模式(Decorator Pattern)允許向一個現有的對象添加新的功能,同時又不改變其結構。這種類型的設計模式屬于結構型模式,它是作為現有的類的一個包裝。
這種設計模式創建了一個裝飾類,用來包裝原有的類,并在保持類方法簽名完整性的前提下,提供了額外的功能。
以InputStream為例,它是一個抽象類:
public abstract class InputStream implements Closeable { ... ... }
并定義有抽象方法
public abstract int read() throws IOException;
該抽象方法由具體的子類去實現,通過InputStream的族譜圖可以看到,直接繼承了InputStream,并且提供某一特定功能的子類有:
ByteArrayInputStream
FileInputStream
ObjectInputStream
PipedInputStream
SequenceInputStream
StringBufferInputStream
這些子類都具有特定的功能,比如說,FileInputStream代表一個文件輸入流并提供讀取文件內容的功能,ObjectInputStream提供了對象反序列化的功能。
InputStream這個抽象類有一個子類與上述其它子類非常不同,這個子類就是FilterInputStream,可參見上圖中的InputStream族譜圖。
翻開FilterInputStream的代碼,我們可以看到,它內部又維護了一個InputStream的成員對象,并且它的所有方法,都是調用這個成員對象的同名方法。
換句話說,FilterInputStream它什么事都不做。就是把調用委托給內部的InputStream成員對象。如下所示:
public class FilterInputStream extends InputStream { protected volatile InputStream in; protected FilterInputStream(InputStream in) { this.in = in; } public int read() throws IOException { return in.read(); } public int read(byte b[]) throws IOException { return read(b, 0, b.length); } public int read(byte b[], int off, int len) throws IOException { return in.read(b, off, len); } public long skip(long n) throws IOException { return in.skip(n); } public int available() throws IOException { return in.available(); } public void close() throws IOException { in.close(); } public synchronized void mark(int readlimit) { in.mark(readlimit); } public synchronized void reset() throws IOException { in.reset(); } public boolean markSupported() { return in.markSupported(); }
FilterInputStream的又有其子類,分別是:
BufferedInputStream
DataInputStream
LineNumberInputStream
PushbackInputStream
雖然從上面代碼看FilterInputStream并沒有做什么有卵用的事,但是它的子類可不同了,以BufferedInputStream為例,這個類提供了提前讀取數據的功能,也就是緩沖的功能。可以看看它的read方法:
public synchronized int read() throws IOException { if (pos >= count) { fill(); if (pos >= count) return -1; } return getBufIfOpen()[pos++] & 0xff; }
可以看到,當pos>=count時,意即需要提前緩沖一些數據的時候到了,那么就會調用fill()將緩沖區加滿,以便后續讀取。由于本文只討論io流的裝飾器模式,所以關于具體實現細節將不會展開討論,比如本文不會討論fill()方法是如何實現的,在這里可以先將它當做一個黑盒子。
從這里可以開始感受到,BufferedInputStream就是一個裝飾者,它能為一個原本沒有緩沖功能的InputStream添加上緩沖的功能。
比如我們常用的FileInputStream,它并沒有緩沖功能,我們每次調用read,都會向操作系統發起調用索要數據。假如我們通過BufferedInputStream來裝飾它,那么每次調用read,會預先向操作系統多拿一些數據,這樣就不知不覺中提高了程序的性能。如以下代碼所示:
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("/home/user/abc.txt")));
同理,對于其它的FilterInputStream的子類,其作用也是一樣的,那就是裝飾一個InputStream,為它添加它原本不具有的功能。OutputStream以及家屬對于裝飾器模式的體現,也以此類推。
JDK中的io流的設計是設計模式中裝飾器模式的一個經典示范,如果細心發現,JDK中還有許多其它設計模式的體現,比如說監聽者模式等等。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/65366.html
摘要:分類一按操作方式類結構字節流和字符流字節流以字節為單位,每次次讀入或讀出是位數據。該對象并不是流體系中的一員,其封裝了字節流,同時還封裝了一個緩沖區字符數組,通過內部的指針來操作字符數組中的數據。 分類一:按操作方式(類結構) 字節流和字符流: 字節流:以字節為單位,每次次讀入或讀出是8位數據。可以讀任何類型數據。 字符流:以字符為單位,每次次讀入或讀出是16位數據。其只能讀取字符類...
摘要:在包下主要包括輸入輸出兩種流,每種輸入輸出流又可分為字節流和字符流兩大類。輸入輸出是從程序運行所在的內存的角度而言的。的輸入流主要由和作為基類,而輸出流主要由和作為基類。 本章主要參考和摘自瘋狂java講義上面的(java編程思想的后面看過后有新的內容再補充進去吧)。 輸入輸出是所有程序都必需的部分————使用輸入機制允許程序讀取外部數據(包括磁盤、光盤等存儲設備上的數據和用戶輸入的...
摘要:流分類由此可見,流很龐大從不同角度進行分類數據分類按處理數據單位分為字節流和字符流。處理數據是音頻視頻文本等一切為字節流,僅能處理文本的為字符流。功能分類節點流和處理流。從向一個特定的設備磁盤網絡等讀寫數據的流稱為節點流,也常被稱為低級流。 嗨嘍,小樂又來了,今天要給大家送上的技術文章是Java重點知識-IO流。 先來看看IO流的思維導圖吧。showImg(https://segmen...
摘要:本文只是尋找設計模式在中的應用。來補全這一塊工廠模式中的應用包線程池解釋和代碼線程池中有線程創建工廠。狀態模式中的應用解釋和代碼根據一個指針的狀態而改變自己的行為適配器模式中的應用解釋和代碼將一個類的接口轉換成客戶希望的另外一個接口。 前言 最近重學設計模式,而且還有很多源碼要看。所以就想一舉兩得。從源碼中尋找設計模式。順便還可以看看源碼。。。本文只是尋找設計模式在java中的應用。優...
摘要:采用通信模型的服務端通常由一個獨立的線程負責監聽客戶端的連接它接收到客戶端連接請求之后為每個客戶端創建一個新的線程進行鏈路處理處理完成之后通過輸出流返回應答給客戶端線程銷毀這就是典型的一請求一應答通信模型該模型最大的問題就是缺乏彈性伸縮能力 BIO 采用 BIO 通信模型的服務端, 通常由一個獨立的 Acceptor 線程負責監聽客戶端的連接, 它接收到客戶端連接請求之后為每個客戶端創...
閱讀 2395·2021-11-11 16:54
閱讀 1204·2021-09-22 15:23
閱讀 3644·2021-09-07 09:59
閱讀 1990·2021-09-02 15:41
閱讀 3283·2021-08-17 10:13
閱讀 3037·2019-08-30 15:53
閱讀 1235·2019-08-30 13:57
閱讀 1210·2019-08-29 15:16