Java_io体系之FilterInputStream/FilterOutputStream简介、走进源码及示例——07
一:FilterInputStream
1、 类功能简介:
过滤器字节输入流、这里不得不提到一种设计模式:Decorator模式、Decorator模式又名包装器(Wrapper),它的主要用途在于给一个对象动态的添加一些额外的职责。与生成子类相比,它更具有灵活性。
有时候,我们需要为一个对象而不是整个类添加一些新的功能,比如,给一个文本区添加一个滚动条的功能。我们可以使用继承机制来实现这一功能,但是这种方法不够灵活,我们无法控制文本区加滚动条的方式和时机。而且当文本区需要添加更多的功能时,比如边框等,需要创建新的类,而当需要组合使用这些功能时无疑将会引起类的爆炸。
我们可以使用一种更为灵活的方法,就是把文本区嵌入到滚动条中。而这个滚动条的类就相当于对文本区的一个装饰。这个装饰(滚动条)必须与被装饰的组件(文本区)继承自同一个接口,这样,用户就不必关心装饰的实现,因为这对他们来说是透明的。装饰会将用户的请求转发给相应的组件(即调用相关的方法),并可能在转发的前后做一些额外的动作(如添加滚动条)。通过这种方法,我们可以根据组合对文本区嵌套不同的装饰,从而添加任意多的功能。这种动态的对对象添加功能的方法不会引起类的爆炸,也具有了更多的灵活性。
以上的方法就是Decorator模式,它通过给对象添加装饰来动态的添加新的功能。
Exp:
当构造FilterInputStream传递进来的是ByteArrayInputStream、因为FilterInputStream与ByteArrayInputStream实现的是同一接口InputStream、那么FileterInputStream对ByteArrayInputStream的装饰对于使用者来说是透明的、他可以在ByteArrayInputStream从父类继承的方法执行之前或者之后进行一些额外操作、实现装饰作用、这里不得不提一句、FilterInputStream仅仅对对InputStream中所有方法进行了重写、并且只调用传入的InputStream子类(一般是低级字节输入流)的那些实现InputStream中的方法、换句话说就是没有对传入的低级字节输入流进行任何的装饰、他的作用是为所有作为装饰类的字节输入流提供一个标准、一个类似于接口的作用。具体的装饰由其子类来完成。
更多内容可以看看前面的:java——IO设计模式:http://blog.csdn.net/crave_shy/article/details/14613423
2、 FilterInputStreamAPI简介:
A:关键字段
//接收构造函数传递进来的 InputStream具体实现类。
protected volatile InputStream in;
B:构造方法
// 根据传入的InputStream具体实现类创建FilterInputStream
protected FilterInputStream(InputStream in) {
this.in = in;
}
C:一般方法
int avaliable();查看当前流中可供读取的字节数。
void close();关闭当前流、释放所有与当前流有关的资源。
synchronized void mark(int readlimit);标记当前流的读取的位子。
boolean markSupport();查看当前流是否支持mark。
int read();读取当前流中的下一个字节、并以整数形式返回、若读取到文件结尾则返回-1。
int read(byte[] b);将当前流中的字节读取到字节数组b中、返回实际读取的字节数
int read(byte[] b, int off, int len);将当前流中的len个字节读取到从下标off开始存放的字节数组b中。
synchronized reset();重置当前流的读取位置到最后一次调用mark方法标记的位置。
long skip(long n);跳过(抛弃)当前流中n个字节。返回实际抛弃的字节数。
3、 源码分析:
package com.chy.io.original.code;
import java.io.IOException;
/**
* FileterInputStream 过滤器字节输入流 、本身什么事都没有做、只是简单的重写InputStream的所有方法。
*/
public class FilterInputStream extends InputStream {
/**
* 接收构造函数传递进来的 InputStream具体实现类。
* 至于 volatile 关键字的意义 参见:http://blog.csdn.net/crave_shy/article/details/14610155
*/
protected volatile InputStream in;
/**
* 根据传入的InputStream具体实现类创建FilterInputStream、并将此实现类赋给全局变量 in、方便重写此实现类从InputStream继承的或重写的所有方法。
*/
protected FilterInputStream(InputStream in) {
this.in = in;
}
/**
* 具体InputStream实现类的read()方法、若子类自己实现的、则是子类的、若子类没有实现则用的是InputStream本身的方法。
* 下面的方法一样。若有不明白的可见前面的InputStream源码分析。
*/
public int read() throws IOException {
return in.read();
}
public int read(byte b[]) throws IOException {
return read(b, 0, b.length);
}
public int read(byte b[], int off, int len) throws IOException {
return in.read(b, off, len);
}
public long skip(long n) throws IOException {
return in.skip(n);
}
public int available() throws IOException {
return in.available();
}
public void close() throws IOException {
in.close();
}
public synchronized void mark(int readlimit) {
in.mark(readlimit);
}
public synchronized void reset() throws IOException {
in.reset();
}
public boolean markSupported() {
return in.markSupported();
}
}
4、 实例演示:
因为其只是一个标准、其方法都是调用传入的InputStream实现类的方法、意义大过于作用、所以这里暂不提供实例、会在有实际装饰效果的类中提供实例、比如后面的DataInputStream、BufferedInputStream、等装饰类的文章中贴出。
二:FilterOutputStream
1、 类功能简介:
过滤字节输出流、与此类是过滤输出流的所有类的超类。这些流位于已存在的输出流(基础输出流)之上,它们将已存在的输出流作为其基本数据接收器,但可能直接传输数据或提供一些额外的功能。
FilterOutputStream
类本身只是简单地重写那些将所有请求传递给所包含输出流的 OutputStream
的所有方法。FilterOutputStream
的子类可进一步地重写这些方法中的一些方法,并且还可以提供一些额外的方法和字段。这是API中关于此流的原话、与对上面FilterInputStream的理解做个对比、多方面的去理解、对比更可以加深印象。
2、 FilterInputStreamAPI简介:
A:关键字段
//传入的OutputStream实现类的引用
protected OutputStream out;
B:构造方法
//通过传入的OutputStream实现类构造FilterOutputStream
public FilterOutputStream(OutputStream out) {
this.out = out;
}
C:一般方法
void write(byte b);将一个字节写入到当前输出流管道中。
void write(byte[] b);将字节数组b中所有字节写入到当前输出流管道中。
void write(byte[] b, int off, int len);将字节数组b从下标off开始、len个字节写入当前输出流管道中
void flush();flush当前流、将当前流中的所有数据冲刷到目的地中。
void close();关闭当前流、释放与当前流有关的所有资源。
3、 源码分析:
package com.chy.io.original.code;
import java.io.IOException;
/**
* 与FilterOutputStream基本相同、
*/
public class FilterOutputStream extends OutputStream {
/**
* 与FileterInputStream 的区别就是不再是volatile
*/
protected OutputStream out;
//通过传入的OutputStream实现类构造FilterOutputStream
public FilterOutputStream(OutputStream out) {
this.out = out;
}
public void write(int b) throws IOException {
out.write(b);
}
public void write(byte b[]) throws IOException {
write(b, 0, b.length);
}
public void write(byte b[], int off, int len) throws IOException {
if ((off | len | (b.length - (len + off)) | (off + len)) < 0)
throw new IndexOutOfBoundsException();
for (int i = 0 ; i < len ; i++) {
write(b[off + i]);
}
}
public void flush() throws IOException {
out.flush();
}
/**
* 关闭此流之前会flush一下。
*/
public void close() throws IOException {
try {
flush();
} catch (IOException ignored) {
}
out.close();
}
}
4、 实例演示:
因为其只是一个标准、其方法都是调用传入的InputStream实现类的方法、意义大过于作用、所以这里暂不提供实例、会在有实际装饰效果的类中提供实例、比如后面的DataInputStream、BufferedInputStream、等装饰类的文章中贴出。
总结:
这一篇没有什么实际的东西、但是他是代表了所有装饰类的一个标准、和实现原理、对我们以后理解接下来的DataInputStream、BufferedInputStream等有很大的帮助、并且有一个使用到的设计模式也值得一提、但也没有针对设计模式长篇大论、毕竟主题不是设计模式、有关此设计模式在IO流中的应用可以看另一篇关于它的文章、FilterInputStream、FilterOutputStream两个类也为我们揭示了一个现象、就是多对java基础类库去应用、深入源码的实现、分析设计原理和过程不但对掌握基础有很好的帮助、也可以潜移默化的影响着我们的思维、让我们更“专业”。