一、模拟BufferedReader
自定义MyBuffereaReader
对于缓冲区而言,里面其实就是封装一个数组,对外提供方法对数组的操作,这些方法最终操作的都是数组的角标
原理:从源中取出数据存入缓冲区,再从缓冲区不断的取出数据,取完后,继续从源中继续取数据,进缓冲区,直至源中的数据取完,用-1做为结束标记
import java.io.*;
class MyBufferedReader {
private FileReader fr;
//定义数组作为缓冲区
private char[] ch = new char[1024];
//定义一个指针用于对数组的操作,当操作数组的最后一个元素后,指针归零
private int pos = 0;
//定义一个计数器,当缓冲区的数据减至0后,继续从源中取数据加到缓冲区中
private int count = 0;
MyBufferedReader(FileReader fr) {
this.fr = fr;
}
public int Myread() throws IOException{
//从源中获取一批数据到缓冲区中,先判断count是否是0
if(count==0) {
count = fr.read(ch);
pos = 0;
}
if (count<0)
return -1;
char temp = ch[pos++];
count--;
return temp;
}
public String MyReadLine() throws IOException{
//将读取的数据存储到缓冲区中
StringBuilder sb = new StringBuilder();
int ch = 0;
while((ch = Myread())!=-1){
if(ch=='\r')
continue;
if(ch=='\n')
return sb.toString();
sb.append((char)ch);
}
if(sb.length()!=0)
return sb.toString();
return null;
}
public void myClose() throws IOException{
fr.close();
}
}
public class Main
{
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("ACM.txt");
MyBufferedReader msb = new MyBufferedReader(fr);
String str = null;
while((str = msb.MyReadLine())!=null){
System.out.println(str);
}
msb.myClose();
}
}
二、装饰设计模式
当对一组对象的功能进行增强时,就可以使用该模式进行问题的解决,上述的自定义MyBufferedReader类就是很好的体现,对于FileReader类比原来的功能简便,当然上述代码写的比较简单
class Room{
public void show(){
System.out.println("房子");
}
}
class NewRoom
{
private Room or;
public NewRoom(OldRoom or) {
// TODO Auto-generated constructor stub
this.or = or;
}
public void show(){
or.show();
System.out.println("平房");
}
}
一定要避免的是修改源代码,当然继承也可以实现功能的增强。
但是继承的话,会让继承体系复杂且麻烦
装饰设计模式和继承的区别:
继承:如果为了增强功能,就要继续写子类,只是为了一个新的NewRoom,就要创建一个子类,NewRoom后出现别墅呢,又要创建子类,逐渐的,导致继承体系越来越臃肿
装饰设计模式:无论NewRoom还是别墅,都是Room的一种,都保持着房子的基本属性
所以,利用装饰设计模式,只需要把被装饰的对象传入即可,可以将缓冲技术单独抽取进行封装,要缓冲区谁将谁和缓冲相关联即可,这样的设计的相对体系会变的简单。
三、LineNumberReader
API文档解释:跟踪行号的缓冲字符输入流。此类定义了方法setLineNumber(int)
和getLineNumber()
,它们可分别用于设置和获取当前行号。
import java.io.*;
public class Main
{
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("ACM.txt");
LineNumberReader lr = new LineNumberReader(fr);
String str = null;
lr.setLineNumber(10);//设置行号从10开始
while((str = lr.readLine())!=null){
System.out.println(str+" line : "+lr.getLineNumber());
}
lr.close();
}
}
此类用的地方不是很多,知道怎么用即可。
四、练习
一定要用字节流文件复制媒体文件
import java.io.*;
public class Main
{
public static void main(String[] args) throws IOException {
//copy_mp3_1();
//copy_mp3_2();//开发建议使用这种
copy_mp3_3();
}
public static void copy_mp3_3() throws IOException {
// TODO Auto-generated method stub
FileInputStream fis = new FileInputStream("D:\\盛夏光年.mp3");
FileOutputStream fos = new FileOutputStream("D:\\盛夏光年3.mp3");
byte[] by = new byte[fis.available()];//局限:文件过大,就不行了
fis.read(by);
fos.write(by);
fos.close();
fis.close();
}
public static void copy_mp3_2() throws IOException {
// TODO Auto-generated method stub
FileInputStream fis = new FileInputStream("D:\\盛夏光年.mp3");
BufferedInputStream br = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream("D:\\盛夏光年2.mp3");
BufferedOutputStream bw = new BufferedOutputStream(fos);
int len = 0;
while((len = br.read())!=-1){
bw.write(len);
bw.flush();
}
br.close();
bw.close();
}
public static void copy_mp3_1() throws IOException {
// TODO Auto-generated method stub
FileInputStream fis = new FileInputStream("D:\\盛夏光年.mp3");
FileOutputStream fos = new FileOutputStream("D:\\盛夏光年1.mp3");
byte[] by = new byte[1024];//注意Mp3文件的字节数,这个数组越接近效率越块
int len = 0;
while((len = fis.read(by))!=-1){
fos.write(len);
fos.flush();
}
fos.close();
fis.close();
}
}
装饰者模式的应用:
/**
* 总结装饰者模式:
* 是你还有你,一切依靠你
* @author Administrator
*
*/
class MyInputStream extends InputStream{ // extends / implements :-> 是你
private InputStream in; //还有你
private int key;
MyInputStream(InputStream in,int key){
this.in = in;
this.key = key;
}
@Override
public int read() throws IOException { // this.in.read() 依靠你
return this.in.read() - key; // 将原文件的读取 更改 , 这个key就成为了文件解密的密码
}
//解密文件时,只需把 key 逆序 写回文件
}
对象增强的手段
* 继承
被增强的对象固定的
增强的内容也是固定的
* 装饰者模式
被增强的对象是可以切换的
增强的内容是固定的
* 动态代理(AOP)
被增强的对象可以切换:Service
增强的内容也可以切换:事务处理
继承:
缺点:
1. 增强的内容是死的,不能动!
2. 被增强的对象也是死的!
装饰者模式
1. 增强的内容是不能修改的!
2. 被增强的对象可以是任意的!