Java中InputStream裝飾器模式的大家族


你好!歡迎閱讀我的博文,你可以跳轉到我的個人博客網站,會有更好的排版效果和功能。
此外,本篇博文為本人Pushy原創,如需轉載請注明出處:https://pushy.site/posts/1519819757

本文寫在po主初學JAVA時,在學習inputStream摸不着頭腦,受Java IO-InputStream家族 -裝飾者模式一文啟發,所以在理清思路時寫下本文。因為初學,如有錯誤,望指正。

因為和輸入流與之對應的還有輸出流(即OutputStream),在此只針對輸入流InputStream討論。

1. 家族老大:

一說起家族中的老大,InputStream自然是當仁不讓,在java的輸入流操作的類中,衍生出的基本子類有,可以理解為這些都是InputStream它的孩子(子類):

InputStream作為所有輸入流中的超類,包含從輸入流讀取數據的基本方法,所有的具體類都包含了這些方法,例如read()方法,它將讀取一個字節並將其以int類型返回,當到達輸入流的結尾時,返回-1,因此我們常常這樣操作:

byte data;
while ((data = (byte) bis.read()) != -1) {
	// 當沒有達到輸入流的結尾時,繼續讀取並打印轉換成char類型的字符:
    System.out.print((char) data);
}

這段代碼不了解不要緊,現在我們開始正式介紹InputStream家族。

2. 家族孩子:

家族中的子類各司其職,老大FileInputStream處理文件流,老二ByteArrayInputStream處理字節數組流...

例如,我們來看下老大是怎么工作的:

import java.io.*;
import java.util.Date;

public class FileInputStreamTest {
    public static void main(String[] args) throws Exception{
        try {
        	// 創建FileInputStream對象:
			FileInputStream fis = new FileInputStream("E:\\text.txt");
            // 得到起始時間:
            long start = System.currentTimeMillis( );
            byte byteData;
            while ((byteData = (byte) bis.read()) != -1) {
                System.out.print((char) byteData);
            }
            // 得到讀取后的結束時間:
            long end = System.currentTimeMillis( );
            // 計算出讀取的時間:
            long diff = end - start;
            System.out.println("讀取的時間時間共:" +  diff);
            fis.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

工作完成后,我們可以得到老大干完活的花費的時間為:1097,但是家族老大嫌這家伙干活太慢了。老大無奈,叫來了它的弟弟老二BufferedInputStream,俗話說啊,兄弟齊心,其利斷金。果不其然,兄弟倆一塊干活效率果然加快了不少:

在如下的代碼中我們可以看到,通過將FileInputStream放到BufferedInputStream中的構造方法中去創建BufferedInputStream對象,這樣FileInputStream也就具有了緩存的輸入流功能。

public class BufInputStream {
    public static void main(String[] args) throws Exception{
        try {
            // 通過緩沖區數據向輸入流添加功能,維護一個內部緩沖區以存儲從底層輸入流讀取的字節:
			BufferedInputStream bis  = new BufferedInputStream(new FileInputStream("E:\\text.txt"));
            long start = System.currentTimeMillis( );
            byte byteData;
            while ((byteData = (byte) fis.read()) != -1) {
                System.out.print((char) byteData);
            }
            long end = System.currentTimeMillis( );
            long diff = end - start;
            System.out.println("讀取的時間時間共:" +  diff);
            bis.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

現在我們來看下兄弟倆一塊工作花費的時間吧:281。嘿!果然快了不少!看來增加緩沖流的功能的效果的確十分明顯。

這下老二在家族的名聲增大了不少,許多的兄弟都找他搭檔干活了。

3. 總結:

通過上文的假設,我們可以明白了在io-InputStream的家族中,采用了裝飾者的設計模式,即不改變原類文件和使用繼承的前提下,動態地擴展一個對象的功能(比如說這里的支持緩沖流),通過創建一個包裝對象(這里的BufferedInputStream),也就是裝飾包裹真實的對象。

例如我們還可以也ByteArrayInputStream中修飾PushbackInputStream類:

PushbackInputStream  pbi = new PushbackInputStream (new ByteArrayInputStream(b));

ByteArrayInputStream是處理字節數組流;PushbackInputStream是向輸入流中添加功能,允許使用unread()方法推回讀取的字節。這樣我們就可以使用pbi對象處理字節數組,還具有推回讀取字節的功能了:

import java.io.*;

public class BAStreamAndPBStream {
    public static void main(String[] args) throws IOException{
        byte[] b = {1,2,3};
        PushbackInputStream  pbi = new PushbackInputStream (new ByteArrayInputStream(b));
        int result;
        while ((result = pbi.read()) != -1) {
            System.out.print(result + " ");
            pbi.unread(result);
            pbi.read();
            System.out.print(result + " ");
        }
        pbi.close();
    }
}

// 運行結果為:
// 1 1 2 2 3 3 

好了,有關InputStream的大家族到這里介紹完了!如果你還有不明白的,可以閱讀一下文章Java IO-InputStream家族 -裝飾者模式


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM