1.MyBufferedReader和MyBufferedInputStream

1.模拟字符读取流的缓冲区:

/*根据readLine原理:自定义一个类包含一个功能和readLine一致的方法来模拟以下BufferedReader方法
*/
package myreadline;
import java.io.FileReader;
import java.io.IOException;class MyBufferedReader{private FileReader r;//需要用到FileReader的read方法,因此初始化时传入FileReader对象private char[] chArr=new char[1024];private int pointer=0;MyBufferedReader(FileReader r){this.r=r;}//自定义readLine方法public String readLine()throws IOException{//自定义功能不在内部处理,而是抛出去,让调用者处理
StringBuilder sb=new StringBuilder();//定义一个临时容器模拟缓冲区int ch=0;while((ch=r.read())!=-1){if(ch=='\r') continue;//读下一个进行判断elseif(ch=='\n')return sb.toString();elsesb.append((char)ch);}   /*
    ①以上代码也不可写成
      if(ch==’\r’||ch==’\n’)
       returnsb.toString()
      因为当读到'\r’ 立即返回改行数据,
      但是下次会读'\n’ 会再次返回,此时StringBuilder无数据
    ②如果当前平台的换行为'\r’以上方法并不适用
      以上方法仅适用与\r\n或\n换行
      此时直接
      if(ch==’\r’)
         return sb.toString();
      else
        return sb.append((char)ch);
 ③对于以上代码可能发生一种情况:当读到文件最后一行:例如:abcd后面没有回车,此时执行不到sb.toString(),也就是说:虽然存入容器但是这一行不能返回.
     那么加上一个判断(如下): 
*/if(sb.length()!=0)return sb.toString();
return null;//此时读到文件末尾

}//模拟自定义缓冲区,把关闭单独封装在一个方法中public void myClose()throws IOException{r.close();}public static void main(String[] args){MyBufferedReader mbr=null;try{mbr=new MyBufferedReader(new FileReader("4_MyBufferedReader.java"));String line=null;while((line=mbr.readLine_2())!=null)System.out.println(line);}catch(IOException e){throw new RuntimeException("读异常");}finally{try{if(mbr!=null)mbr.myClose();}catch(IOException e){throw new RuntimeException("关闭异常");}}}
}

/*
如果不利用StringBuilder而利用
字符数组
*/
public  String readLine_2()throws IOException{pointer=0;int ch=0;while((ch=r.read())!=-1){if(ch=='\r')continue;elseif(ch=='\n')return new String(chArr,0,pointer);elsechArr[pointer++]=(char)ch; }if(pointer!=0)return new String(chArr,0,pointer);return null;
}

2.模拟字节读取流缓冲区:

/*
自定义缓冲区:算法思想:参照示意图
*/  package mybuffered;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io. BufferedOutputStream;
class MyBufferedInputStream{private byte[] buff=new byte[1024];private InputStream is=null;private int pointer=0;//指针用于取出缓冲区(数组)中的元素private int count=0;//计数器用于记录每次从文件中取出的字节数
  MyBufferedInputStream(InputStream is){this.is=is;}public int myBufferedRead()throws IOException{if(count==0){//只有当缓冲区中的数据被读完时,再从文件中//取一部分数据count=is.read(buff);pointer=0;//当count==0,把指针重新移到0角标
     }if(count!=-1){//是否到达文件尾--count;//读取一个字节,count-1return (int)buff[pointer++] & 255;//0x00ff
     }elsereturn -1;}public void close()throws IOException{is.close();}
}class TestBuffered{public static void main(String[] args)throws IOException{
  //用自定义缓冲区拷贝MP3
 MyBufferedInputStream mbis=new MyBufferedInputStream(new FileInputStream("e:\\song\\Amy Diamond - Heartbeats.mp3"));BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("c:\\Hertbeats.mp3"));long start=System.currentTimeMillis();int aByte=0;System.out.println(aByte=(mbis.myBufferedRead()));
while((aByte=(mbis.myBufferedRead()))!=-1){//从自定义缓冲区中读一个字节,写入到系统的缓冲区
   bos.write(aByte);bos.flush();}long end=System.currentTimeMillis();System.out.println(end-start+"ms");//时间的长短和cpu性能以及其它因素有关
  bos.close();mbis.close();}
}

2.装饰设计模式:

①概述:

/*
装饰设计模式:(目前学的第三种设计模式)
    当想要对已有的对象进行功能增强时可以定义类,将已有对象(new FileReader)传入,基于已有的功能(read),并提供加强功能(myReadLine).那么自定义的该类成为装饰类.装饰类通常会通过构造方法接收被装饰的对象
并基于被装饰的对象的功能,提供更强的功能*/
//例如:增强人的吃饭功能
class Person{public void eat(){System.out.println("吃饭");}
}
class SuperPerson{private Person p;SuperPerson(Person p){this.p=p;}public void superEat(){System.out.println("喝小酒");p.eat();System.out.println("甜点");System.out.println("整一根");}
}
class PersonDemo{public static void main(String[] args){Person p=new Person();    p.eat();new SuperPerson(p).superEat();}
}
/*到目前为止已经学到3中设计模式:1.单例设计模式2.模板方法设计模式3.装饰设计模式
*/

②※装饰相对继承优点:

/*在人吃饭例子中,可以不用装饰类,我直接让SuperPerson extends Person,然后复写eat方法不也OK?在举例说明为什么要有装饰设计模式?//MyTextReader类用来操作文件读取,为了提高读操作效率,使用缓冲区技术//又定义一个类MyBufferedTextReader继承它,提供更高效的readLine方法MyReader  <--MyTextReader<--MyBufferedTextReader<--MyMediaReader<--MyBufferedMediaReader//读取多媒体文件,然后为了提高读效率,使用缓冲区<--MyDataReader<--MyBufferedDataReader//同理......  那么,我后期在来个类用于操作读取其它文件,为了高效还得定义缓冲区子类,产生一些缺点:1.使整个体系变得异常冗杂2.后期的扩展性极差那么干脆:找到其参数的共同类型.通过多态形式.可以提高扩展性MyBufferedReader extends MyReader{private MyReader mr;pubic MyBufferedReader(MyReader mr){//MyReader的子类对象均能传入this.mr=mr;                           //谁需要使用缓冲技术,把它传进来}}简化了原有体系结构:MyReader<--MyTextReader<--MyMediaReader<--MyDataReader   <--MyBufferedReader*//*
装饰设计模式对比继承:1.装饰设计模式比继承更加灵活提高扩展性,避免了继承的冗杂而且降低了类与类之间关系2.装饰类因为增强已有对象,具备的功能和已有的功能是相同的只不过提供了更强的功能(这个功能是原有的增强,而不是从本质上改变原有功能:在Reader体系中,例如:装饰类BufferedReader,其中readLine就是增强了FileReader中read功能)那么装饰类和被装饰类通常是同属于一个体系(具有共同的父类/父接口)
*/

鉴于以上我们可以把自定义缓冲区的代码优化下: (改进自定义字符读取流缓冲区)

//把MyBufferedReader修改为装饰类:
package myreadline;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
public class MyBufferedReader2 extends Reader{//继承Reader,那么必须复写Reader中抽象方法,不然无法创建对象
 private Reader r;
public MyBufferedReader2(Reader r){//多态提高扩展性this.r=r;  
  }public String readLine()throws IOException{StringBuilder sb=new StringBuilder();int ch=0;while((ch=r.read())!=-1){if(ch=='\r') continue;//读下一个进行判断elseif(ch=='\n')return sb.toString();elsesb.append((char)ch);}   if(sb.length()!=0)return sb.toString();
return null;
}//复写close方法public void close()throws IOException{r.close();}//复写abstract int read(char[] cbuf, int off, int len)public int read(char[] cbuf, int off, int len)throws IOException{return 

r

.read(cbuf,off,len);//利用了 传入对象已复写该方法
  }public static void main(String[] args){MyBufferedReader mbr=null;try{mbr=new MyBufferedReader(new FileReader("4_MyBufferedReader.java"));String line=null;while((line=mbr.readLine())!=null)System.out.println(line);}catch(IOException e){throw new RuntimeException("读异常");}finally{try{if(mbr!=null)mbr.close();}catch(IOException e){throw new RuntimeException("关闭异常");}}}
}

3.BufferedReader子类LineNumberReader(相对于BufferedReader提供更强功能)

①.LineNumberReader示例:

/*
在BufferedReader下有一个子类:LineNumberReader跟踪行号的缓冲字符输入流,进一步加强功能.打印每行的同时可以带上行号
*/
package bufferedreader;
import java.io.LineNumberReader;
import java.io.FileReader;
import java.io.IOException;
class LineNumberReaderDemo{public static void main(String[] args){LineNumberReader lnr=null;try{lnr=new LineNumberReader(new FileReader("7_LineNumberReader.java"));String line=null;lnr.setLineNumber(10);//那么行号将从11开始while((line=lnr.readLine())!=null)System.out.println(lnr.getLineNumber()+":"+line);}catch(IOException e){e.printStackTrace();}finally{try{if(lnr!=null)lnr.close();}catch(IOException e){e.printStackTrace();}}}
}

②自定义MyLineNumberReader方法:

package mylinenumber;import java.io.Reader;
import java.io.FileReader;
import java.io.IOException;
import myreadline.MyBufferedReader2;class MyLineNumberReader extends MyBufferedReader2{//在MyBufferedReader2已有方法,不再重复定义private int lineNumber=0;//行号public MyLineNumberReader(Reader r){super(r);}//设置行号public void mySetLineNumber(int lineNumber){this.lineNumber=lineNumber;}//获取行号public int myGetLineNumber(){return lineNumber; }public String myReadLine()throws IOException{++lineNumber;//读一行自增一次return super.readLine();//提高代码重用性
    }}class MyLineNumberDemo{public static void main(String[] args){MyLineNumberReader mlnr=null;try{mlnr=new MyLineNumberReader(new FileReader("8_MyLineNumberReader.java"));String line=null;mlnr.mySetLineNumber(100);while((line=mlnr.myReadLine())!=null)System.out.println(mlnr.myGetLineNumber()+":"+line);}catch(IOException e){e.printStackTrace();}finally{try{if(mlnr!=null)mlnr.close();}catch(IOException e){e.printStackTrace();}}}
}

转载于:https://www.cnblogs.com/yiqiu2324/archive/2013/05/18/3085750.html

day19(中)_IO流3(模拟缓冲区,装饰设计模式)相关推荐

  1. 【02】Java进阶:13-IO资源的处理、属性集、缓冲流、转换流、序列化、打印流、装饰设计模式、commons-io工具包

    day13[Properties类.缓冲流.转换流.序列化流.装饰者模式.commons-io工具包] 今日内容 IO异常处理 Properties类 缓冲流 转换流 序列化\反序列化流 打印流 装饰 ...

  2. 黑马程序员-JAVA基础-IO流中的装饰设计模式

    ------- android培训.java培训.期待与您交流!------- 装饰设计模式: 当想要对已有的对象进行功能增强时,可以定义类,将已有的对象传入,基于已有的功能,并提供加强功能.那么,自 ...

  3. JDK源码解析 —— IO流中的包装类使用到了装饰者模式

    JDK源码解析 IO流中的包装类使用到了装饰者模式. BufferedInputStream, BufferedOutputStream, BufferedReader, BufferedWriter ...

  4. java基础学习_IO流03_字符流、IO流小结、案例_day21总结

    java基础学习_IO流03_字符流.IO流小结.案例_day21总结 ================================================================ ...

  5. 装饰设计模式缓冲流转换流序列化与反序列化

    装饰设计模式&缓冲流&转换流&序列化与反序列化 - 能够使用字节缓冲流读取数据到程序1.创建BufferedInputStream对象,构造方法中传递FileInputStre ...

  6. 5_异常_多线程_设计模式_IO流_网络编程_反射

    JavaSE_第五周 异常 异常的概念 什么是异常 概念 概念:程序在运行过程中出现的特殊情况异常-----通过Jvm将异常的信息打印在控制台---告诉开发者(当前程序在某个环节出现了哪些问题!) 异 ...

  7. JavaSE(字符流、IO资源的处理、属性集、ResourceBundle工具类、缓冲流、转换流、序列化、打印流、装饰设计模式、commons-io工具包)

    JavaSE 字符流 字符输入流[Reader] 字符输入流Reader类的概述 字符输入流Reader类的常用方法 FileReader类 FileReader类的概述 FileReader类的构造 ...

  8. Java中IO流,输入输出流概述与总结(转载自别先生文章)

    Java中IO流,输入输出流概述与总结 总结的很粗糙,以后时间富裕了好好修改一下. 1:Java语言定义了许多类专门负责各种方式的输入或者输出,这些类都被放在java.io包中.其中, 所有输入流类都 ...

  9. 【Java网络编程与IO流】Java中IO流分为几种?字符流、字节流、缓冲流、输入流、输出流、节点流、处理流

    Java网络编程与IO流目录: [Java网络编程与IO流]Java中IO流分为几种?字符流.字节流.缓冲流.输入流.输出流.节点流.处理流 [Java网络编程与IO流]计算机网络常见面试题高频核心考 ...

最新文章

  1. 51CTO让我成长【我与51CTO的故事】
  2. java.lang.IllegalStateException: Failed to read Class-Path attribute from manifest of jar file:/XXX
  3. 视频格式转换工具使用
  4. java6集合编程题
  5. 音视频技术开发周刊 | 198
  6. 5大过程组与整体管理
  7. python开发出来的crm系统_用Python打造一个CRM系统(三)
  8. java解析vue对象数组,Java数组
  9. python设计模式2-工厂方法模式
  10. mysql重新编译_重新编译mysqld_exporter0.10-阿里云开发者社区
  11. 学完之后,有什么证书发吗?要另外收费吗?收费多少? 学员每天的上课时间是怎样安排的?...
  12. Visio 2019/2016中文版零基础入门视频教程
  13. 厚着脸皮求领导写了一篇java小白进阶大牛之路!!!
  14. 服务器网卡光模块位置,收藏:详解服务器、磁盘和网卡知识
  15. SAP小磁带备份注意事项
  16. scaner从外网到内网域渗透笔记
  17. java实现等待程序响应_java – Ning:连接到websocket并等待响应
  18. 网络游戏《丛林战争》开发与学习之(一):网络编程的基础知识
  19. 从零开始计算机网络——计算机网络课程的了解初步认识计算机网络
  20. 初链-解读初链白皮书

热门文章

  1. 集成电路史上著名的十个人,有几个中国人?
  2. MongoDB数据库基本操作笔记
  3. 职场中不要问程序员这五类问题
  4. php动态添加查询,php动态添加url查询参数的方法,php动态url参数_PHP教程
  5. Java后端带参跨域访问_java后端解决请求跨域
  6. 用于大型的科学计算的计算机,科学计算器广泛适用于大、中、小学生、教师、科研人员及其他各界...
  7. mybatis插入图片处理--mysql
  8. figma设计_在Figma中使用隔片移交设计
  9. 深入浅出之正则表达式(二)
  10. 如何读懂并写出装逼的函数式代码 1