Java I/O全文摘要(六)過濾流,過濾流

1.過濾流

"Filter streams are used for encryption, compression, translation, buffering, and much more."

過濾流用於加密,壓縮,翻譯,緩衝和其他功能。


過濾器從預先存在的流中讀取數據,然後在傳遞到客戶端程序之前,有機會改變他的數據。

可將多個流連成一條鏈對底層的流使用。

過濾流不僅僅移除掉你不想要的,還能增加你想要的。


2. 過濾流類

兩個超級類:java.io.FilterInputStream和java.io.FilterOutputStream

public class FilterInputStream extends InputStream
public class FilterOutputStream extends OutputStream

它們都只有一個protected類型的結構體

protected FilterInputStream(InputStream in)
protected FilterOutputStream(OutputStream out)

由於結構體是保護的,所以需要採用子類實現部分功能,並提供public的結構體

它們使用一個超級類作爲成員變量,然後對這個成員變量進行修飾

protected InputStream in
protected OutputStream out


其實除了構造方法,常用的是下面這些:

對於FilterInputStream:

public int  read( ) throws IOException
public int  read(byte[] data) throws IOException
public int  read(byte[] data, int offset, int length) throws IOException
public long skip(long n) throws IOException
public int  available( ) throws IOException
public void close( ) throws IOException
public void mark(int readlimit)
public void reset( ) throws IOException
public boolean markSupported( )

對於FilterOutputStream:

public void write(int b) throws IOException
public void write(byte[] data) throws IOException
public void write(byte[] data, int offset, int length) throws IOException
public void flush( ) throws IOException
public void close( ) throws IOException


所以,默認的行爲只是轉發相應的操作,例如:

public long skip(long n) throws IOException {
  in.skip(n);
}

以及

public void close( ) throws IOException {
  out.close( );
}

由於沒有無參構造函數,所以在子類中你必須顯示的調用父類的構造函數。


3. 過濾流類的子類

java.io包中包含了很多有用的過濾流子類

BufferedInputStream and BufferedOutputStream爲原有的輸入輸出提供了緩衝字節數組,這樣,再使用這個流就不必要從native方式去讀取數據了。

這在很多時候能提高性能,並且運行輸入流重讀操作。


java.io.PrintStream允許非常簡單的打印原始類型,對象和字符串字母。

使用平臺默認的編碼集來轉化字符到字節。

System.out and System.err是最出名的java.io.PrintStream

你也可以自己實例化它。例如結合使用PrintStream to aFileOutputStream


PushbackInputStream擁有一個字節的回退緩衝,這樣程序可以實現"unread"最後一個字符。

下一次讀取時,這個字符將被重新讀取。


ProgressMonitorInputStream將告知用戶讀了多少,還有多少可讀。


DataInputStream and DataOutputStream將用平臺獨立的方式讀寫Java原始類型和String

(Big-endian for integer types, IEEE-754 forfloats anddoubles, a variant of UTF-8 for strings.)


ObjectInputStream andObjectOutputStream繼承自DataInputStream and DataOutputStream,但它卻可以像讀取原始類型一樣讀取整個Java對象。


java.util.zip包中也包含了一些過濾流。用於壓縮和解壓。由於壓縮和解壓容易使得文件損壞,所以提供了一些校驗和。


java.util.security包中包含了DigestInputStream andDigestOutputStream


JCE也提供了兩個加密過濾流:CipherInputStream andCipherOutputStream


4.Buffered Streams

buffer流會讀取超過所需的內容,而在需要時,可以直接從buffer中取出內容而無需再從實質的流中讀取。

兩個InputStream,兩個OutputStream的構造方法

public BufferedInputStream(InputStream in)
public BufferedInputStream(InputStream in, int size)
public BufferedOutputStream(OutputStream out)
public BufferedOutputStream(OutputStream out, int size)

第一個參數指定了實際的流(當然,它也可能被裝飾),第二個參數則是指定緩衝的大小。

沒有指定則是2048,最佳實踐通常取決於塊的大小,小於512或者大於8192通常都不大合適。

理想情況是塊的整數倍。

當然,你可能在不可靠的網絡流上使用較小的緩衝。

URL u = new URL("http://java.sun.com");
BufferedInputStream bis = new BufferedInputStream(u.openStream( ), 256);

這種情況下,使用了256長度的緩衝尺寸。


5. 一個緩衝流的例子

import java.io.*;
public class BufferedStreamCopier {
  public static void main(String[] args) {
    try {
      copy(System.in, System.out);
    }
    catch (IOException ex) {
      System.err.println(ex);
    }
  }

  public static void copy(InputStream in, OutputStream out)
   throws IOException {
    BufferedInputStream 
 bin = new BufferedInputStream(in);
    BufferedOutputStream bout = new BufferedOutputStream(out);
    while (true) {
      int datum = bin.read( );
      if (datum == -1) break;
      bout.write(datum);
    }
    bout.flush( );
  }
}

copy方法1字節1字節的拷貝,通常是沒有效率的,但是如果使用了緩衝流,那麼拷貝工作是在內存中進行的,就會變得有效率的多了。

有意的調用了flush方法,這是因爲只有在緩衝流flush或者到達緩衝滿時,纔會使得實質的流到達數據的終點。

因此,調用flush()是十分有必要的。


6. 緩衝輸入流(BufferedInputStream)的細節

BufferedInputStream繼承自InputStream,它僅僅覆蓋了父類的方法,沒有提供任何新的方法。

 標記(Marking)和重置 (resetting)是支持的。


在Java版本1.2及之後,兩個多byte讀取都是採用逐字方式讀取的。

buffer和狀態信息都保存在受保護的域中。

protected byte[] buf
protected int    count
protected int    pos
protected int    markpos
protected int    marklimit

其中:buf是保存緩衝的byte數組,count是buffer中的byte數量,read()返回的index是pos,標記叫做markpos,領先於mark位置的長度使得mark無效叫做marklimit。


7 緩衝輸出流(BufferedOunputStream)的細節

BufferedInputStream很相似,它也有buf數組和pos表示位置

protected byte buf[]
protected int  pos

PushbackInputStream

java.io.PushbackInputStream提供了pushback緩衝,使用字節可以處於"未讀取"狀態。

換言之,可以添加byte到流裏面,然後讀取它。

PushbackInputStream允許程序在讀取時往流裏添加數據。

下次從這個流中讀取數據,這些未被讀取的數據將被讀取。


默認情況下,這個流的buffer只有1字節長。

你可以通過構造方法來修改它.

public PushbackInputStream(InputStream in)
public PushbackInputStream(InputStream in, int size)

Unread data 將被放入棧中。

也就是如果你添加0,1,2 最終讀出來會是2,1,0

樣例代碼如下:

PushbackInputStream in = new PushbackInputStream(System.in, 5);
in.unread(0);
in.unread(1);
in.unread(2);
System.out.println(in.read( ));
System.out.println(in.read( ));
System.out.println(in.read( ));

使用場景:

考慮Java語句 int count=7;. 編譯器並不知道t是變量名的最後一個字母,直到讀到等於號"="。

這時,可以unread =號

另一個是添加一些東西,如Unix和Mac的換行分割的問題。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章