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
8 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的換行分割的問題。