I/O操作中用到装饰模式(转自chjavach)

[b]1,java io中装饰器的利用例子[/b]
package decorationApp;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.FileInputStream;
//装饰器的典型应用
public class IOTest {
public static void main(String[] args)throws Exception {
//流式读取文件
DataInputStream din = null;
try{
din = new DataInputStream(
new BufferedInputStream(
new FileInputStream("IOTest.txt") //文件放在项目目录下,不是src下,也不是同包下
)
);
//然后就可以获取文件内容了
byte bs []= new byte[din.available()];
din.read(bs);
String content = new String(bs);
System.out.println("文件内容===="+content);
}finally{
if(din!=null)din.close();
}
}
}

仔细观察上面的代码,会发现最里层是一个FileInputStream对象,然后把它传递给一个BufferedInputStream对象,经过BufferedInputStream处理过后,再把处理过后的对象传递给了DataInputStream对象进行处理,这个过程其实就是装饰器的组装过程,FileInputStream对象相当于原始的被装饰的对象,而BufferedInputStream对象和DataInputStream对象则相当于装饰器。

[b]2,自己实现的I/O流的装饰器[/b]
来个功能简单点的,实现把英文加密存放吧,也谈不上什么加密算法,就是把英文字母向后移动两个位置,比如:a变成c,b变成d,以此类推,最后的y变成a,z就变成b,而且为了简单,只处理小写的,够简单的吧。

package decorationApp;

import java.io.IOException;
import java.io.OutputStream;

/**
* 实现简单的加密,对OutputStream进行装饰
*/
public class EncryptOutputStream extends OutputStream{
//持有被装饰的对象
private OutputStream os = null;

public EncryptOutputStream(OutputStream os){
this.os = os;
}
public void write(int a) throws IOException {
//先统一向后移动两位
a = a+2;
//97是小写的a的码值
if(a >= (97+26)){
//如果大于,表示已经是y或者z了,减去26就回到a或者b了
a = a-26;
}
this.os.write(a);
}
}

测试程序:
package decorationApp;

import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.FileOutputStream;

public class Client {
public static void main(String[] args) throws Exception {
//流式输出文件
DataOutputStream dout = new DataOutputStream(
new BufferedOutputStream(
//这是我们加的装饰器
new EncryptOutputStream(
new FileOutputStream("MyEncrypt.txt")))); //如果没有项目目录下没有此文件,会自动创建该文件
//然后就可以输出内容了
dout.write("abcdxyz".getBytes()); //如果文件中有内容将被重新写入
dout.close();
}
}

生成的MyEncrypt.txt文件中内容:cdefzab

如果上面的程序,装饰器的顺序改变如下:
//流式输出文件
DataOutputStream dout = new DataOutputStream(
//换了个位置
new EncryptOutputStream (
new BufferedOutputStream(
new FileOutputStream("MyEncrypt.txt"))));


这个时候输出的文件一片空白,什么都没有。这是哪里出了问题呢?
(1)先看看成功输出流中的内容的写法的运行过程:




•当执行到“dout.write("abcdxyz".getBytes());”这句话的时候,会调用DataOutputStream的write方法,把数据输出到BufferedOutputStream中;
•由于BufferedOutputStream流是一个带缓存的流,它默认缓存8192byte,也就是默认流中的缓存数据到了8192byte,它才会自动输出缓存中的数据;
•而目前要输出的字节肯定不到8192byte,因此数据就被缓存在BufferedOutputStream流中了,而不会被自动输出
•当执行到“dout.close();”这句话的时候:会调用关闭DataOutputStream流,这会转调到传入DataOutputStream中的流的close方法,也就是BufferedOutputStream的close方法,而BufferedOutputStream的close方法继承自FilterOutputStream,在FilterOutputStream的close方法实现里面,会先调用输出流的方法flush,然后关闭流。也就是此时BufferedOutputStream流中缓存的数据会被强制输出;
•BufferedOutputStream流中缓存的数据被强制输出到EncryptOutputStream流,也就是我们自己实现的流,没有缓存,经过处理后继续输出;
•EncryptOutputStream流会把数据输出到FileOutputStream中,FileOutputStream会直接把数据输出到文件中,因此,这种实现方式会输出文件的内容。




(2)再来看看不能输出流中的内容的写法的运行过程:

•当执行到“dout.write("abcdxyz".getBytes());”这句话的时候,会调用DataOutputStream的write方法,把数据输出到EncryptOutputStream中;
•EncryptOutputStream流,也就是我们自己实现的流,没有缓存,经过处理后继续输出,把数据输出到BufferedOutputStream中;
•由于BufferedOutputStream流是一个带缓存的流,它默认缓存8192byte,也就是默认流中的缓存数据到了8192byte,它才会自动输出缓存中的数据;
•而目前要输出的字节肯定不到8192byte,因此数据就被缓存在BufferedOutputStream流中了,而不会被自动输出
•当执行到“dout.close();”这句话的时候:会调用关闭DataOutputStream流,这会转调到传入DataOutputStream流中的流的close方法,也就是EncryptOutputStream的close方法,而EncryptOutputStream的close方法继承自OutputStream,在OutputStream的close方法实现里面,是个空方法,什么都没有做。因此,这种实现方式没有flush流的数据,也就不会输出文件的内容,自然是一片空白了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值