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 FilterInputStream(InputStream in)
protected FilterOutputStream(OutputStream out)
它们使用一个超级类作为成员变量,然后对这个成员变量进行修饰
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);
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( );
}
}
有意的调用了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)
也就是如果你添加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的换行分割的问题。