天天看點

Java I/O總結——InputStream

在前面介紹了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 I/O總結——InputStream

在這裡,我們主要介紹java.io包。

流的分類,如下圖所示:

Java I/O總結——InputStream

過濾流就是采用了Decorator(裝飾)模式,後面我們會為大家詳細說明。

Java I/O的設計原則(Decorator(裝飾)模式)

Java I/O總結——InputStream

java.io.InputStream類總結

首先學習基類java.io.InputStream(讀取一系列位元組的對象),以及在它基礎上派生出來的子類,類結構圖如下圖所示(單擊檢視大圖檔):

Java I/O總結——InputStream

InputStream是一個抽象類,是所有資料形式為位元組的輸入流的父類,為基于位元組的資料輸入定義了基本操作方法。實際上,InputStream的子類大部分都沒有增加任何其他的接口函數(在上面的類結構圖中就可以發現),是以在看InputStream子類的時候,我們主要學習其構造函數。

Java I/O中是如何采用Decorator(裝飾)模式的呢?下面為大家詳細說明,看到FilterInputStream類(也就前面說的過濾流,後面你會發現更多的過濾流),你是否發現了?對,就是FilterInputStream類,她就相當于Decorator(裝飾)模式中的Decorator類,而且的BufferedInputStream、DataInputStream、PushbackInputStream則相當于是ConcreateDecorator,如下圖所示:

Java I/O總結——InputStream

那麼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。

上面的代碼可以使用如下圖來表示,更加的直覺:

Java I/O總結——InputStream

大家再去仔細看下Decorator(裝飾)模式中的例子:一個具有邊框與滾動條的文本顯示視窗,是不是很相似!

總結說明

整個java.io的核心都是采用了Decorator(裝飾)模式,了解了Decorator(裝飾)模式,對Java I/O的學習是不是更加簡單了,這裡我隻是将自己的學習的筆記整理後與大家分享。java.io.InputStream類結構圖,建議大家列印出來後,在以後使用時候在拿出來看下,就知道如何使用了。當然這張類圖結構還不完整(缺少其他一些類),列印出來後自己補充說明,把這張類圖逐漸完善。

原文:http://www.moandroid.com/?p=1435