在前面介紹了Decorator(裝飾)模式,讓我自己想起了剛開始工作時那段“痛并快樂”的學習時光。在學習Android網絡方面,也發現網絡方面的很多内容都與Java I/O有關,是以暫時先停下Android網絡方面的學習,把Java I/O完整的學習下。我們将按照基類的順序:InputStream、OutPutStream、Reader、Writer來分别對Java I/O加以總結。
在這裡強調以下2點:
- 如果你對設計模式中的Decorator(裝飾)不是很了解,請仔細閱讀:從new BufferedReader(new InputStreamReader(conn.getInputStream()))想到的,在這篇部落格中,我們詳細介紹了Decortor(裝飾)模式。在了解了Decorator(裝飾)後,我們對學習Java I/O的學習會容易很多,因為Java I/O的核心就是采用了Decorator(裝飾)模式。
- Java I/O系列的部落格是我在學習Java I/O的基礎上,對Java I/O的總結,關于Java I/O方面的基礎知識,我們在這裡不詳細說明。如果你對Java I/O完全不了解,請先找些關于Java I/O方面的資料簡要閱讀下。在簡要學習的基礎上,我們将Java I/O方面的資料整理,幫助大家對Java I/O的知識更加清晰些。
Java I/O相關的包,如下表格所示:
在這裡,我們主要介紹java.io包。
流的分類,如下圖所示:
過濾流就是采用了Decorator(裝飾)模式,後面我們會為大家詳細說明。
Java I/O的設計原則(Decorator(裝飾)模式)
java.io.InputStream類總結
首先學習基類java.io.InputStream(讀取一系列位元組的對象),以及在它基礎上派生出來的子類,類結構圖如下圖所示(單擊檢視大圖檔):
InputStream是一個抽象類,是所有資料形式為位元組的輸入流的父類,為基于位元組的資料輸入定義了基本操作方法。實際上,InputStream的子類大部分都沒有增加任何其他的接口函數(在上面的類結構圖中就可以發現),是以在看InputStream子類的時候,我們主要學習其構造函數。
Java I/O中是如何采用Decorator(裝飾)模式的呢?下面為大家詳細說明,看到FilterInputStream類(也就前面說的過濾流,後面你會發現更多的過濾流),你是否發現了?對,就是FilterInputStream類,她就相當于Decorator(裝飾)模式中的Decorator類,而且的BufferedInputStream、DataInputStream、PushbackInputStream則相當于是ConcreateDecorator,如下圖所示:
那麼Java I/O中到底是如何使用的了?Decorator(裝飾)模式的主要意圖是:動态地給一個對象添加一些額外的職責,這句話很抽象,我們結合Java I/O舉個具體的例子:比如說我們讀取檔案,首先打開檔案擷取到File,然後我們再建立一個FileInputStream,然後讀取檔案。讀取檔案是一個很費時的操作,尤其是需要多次的讀寫檔案。
自己的一點經曆與大家分享:在一次C++程式設計的時候,需要打開檔案然後每次讀取一小段資料,後來發現整個程式的效率比較低,通過測試代碼發現,對資料的讀取方面占用太多的時間。盡管C++對檔案的讀取中實作了緩沖機制,但是好像這個緩沖區域比較小,然後通過_setbuf()函數增大緩沖區,發現程式的數度居然提升了很多。
那麼在Java中采用面向對象的思想:BufferedInputStream實作了對資料讀取的緩沖機制,通過FileInputStream來讀取資料,BufferedInputStream将已經讀取的資料存儲到緩沖區,BufferedInputStream相當于對FileInputStream進行了“裝飾”。
File file = new File(“c://moandroid.txt”,true);
InputStream is = new BufferedInputStream(new FileInputStream(file));
long length = file.length();
if(length>Integer.MAX_VALUE)
{
System.out.println(“source file is too large”);
return ;
}
byte[] bytes = new byte[(int)length];
int offset = 0,numRead = 0;
while( offset<bytes.length && (numRead = is.read(bytes,offset,bytes.length-offset))>= 0)
offset += numRead;
if(offset<bytes.length)
throw new IOException(“Could not completely read file”+file.getName());
is.close();
DataInputStream類的功能則更加強大,其在InputStream類的基礎上增加了很多讀取函數的接口,舉個例子如下:
InputStream is = null;
try
{
File file = new File(“c://moandroid.txt”,true);
is = new DataInputStream(new FileInputStream(file));
int intData = is.readInt();
boolean boolData = is.readBoolean();
}
catch(FileNotFoundException e)
{
e.printStackTree();
}
catch(IOException e)
{
e.printStackTree();
}
finally
{
if(is!=null)
{
try{is.close();}
catch(IOException e){}
}
}
這裡補充說明:DataInputStream讀取的順序必須和實際資料存儲的順序一緻,否則會出現IOException。
上面的代碼可以使用如下圖來表示,更加的直覺:
大家再去仔細看下Decorator(裝飾)模式中的例子:一個具有邊框與滾動條的文本顯示視窗,是不是很相似!
總結說明
整個java.io的核心都是采用了Decorator(裝飾)模式,了解了Decorator(裝飾)模式,對Java I/O的學習是不是更加簡單了,這裡我隻是将自己的學習的筆記整理後與大家分享。java.io.InputStream類結構圖,建議大家列印出來後,在以後使用時候在拿出來看下,就知道如何使用了。當然這張類圖結構還不完整(缺少其他一些類),列印出來後自己補充說明,把這張類圖逐漸完善。
原文:http://www.moandroid.com/?p=1435