JAVA自学教程之IO流(三):缓冲区2 & 装饰设计模式



JAVA自学教程之IO流(三):缓冲区2 & 装饰设计模式。

一、模拟BufferedReader

自定义MyBuffereaReader

对于缓冲区而言,里面其实就是封装一个数组,对外提供方法对数组的操作,这些方法最终操作的都是数组的角标

原理:从源中取出数据存入缓冲区,再从缓冲区不断的取出数据,取完后,继续从源中继续取数据,进缓冲区,直至源中的数据取完,用-1做为结束标记

 

  1. import java.io.*;
  2. class MyBufferedReader {
  3.     private FileReader fr;
  4.     //定义数组作为缓冲区
  5.     private char[] ch = new char[1024];
  6.     //定义一个指针用于对数组的操作,当操作数组的最后一个元素后,指针归零
  7.     private int pos = 0;
  8.     //定义一个计数器,当缓冲区的数据减至0后,继续从源中取数据加到缓冲区中
  9.     private int count = 0;
  10.     MyBufferedReader(FileReader fr) {
  11.         this.fr = fr;
  12.     }
  13.     public int Myread() throws IOException{
  14.         //从源中获取一批数据到缓冲区中,先判断count是否是0
  15.         if(count==0) {
  16.             count = fr.read(ch);
  17.             pos = 0;
  18.         }
  19.             if (count<0)
  20.                 return -1;
  21.             char temp = ch[pos++];
  22.             count–;
  23.             return temp;
  24.     }
  25.     public String MyReadLine() throws IOException{
  26.         //将读取的数据存储到缓冲区中
  27.         StringBuilder sb = new StringBuilder();
  28.         int ch = 0;
  29.         while((ch = Myread())!=-1){
  30.             if(ch==’\r’)
  31.                 continue;
  32.             if(ch==’\n’)
  33.                 return sb.toString();
  34.             sb.append((char)ch);
  35.         }
  36.         if(sb.length()!=0)
  37.             return sb.toString();
  38.         return null;
  39.     }
  40.     public void myClose() throws IOException{
  41.         fr.close();
  42.     }
  43. }
  44. public class Main
  45. {
  46.     public static void main(String[] args) throws IOException {
  47.         FileReader fr = new FileReader(“ACM.txt”);
  48.         MyBufferedReader msb = new MyBufferedReader(fr);
  49.         String str = null;
  50.     while((str = msb.MyReadLine())!=null){
  51.             System.out.println(str);
  52.         }
  53.         msb.myClose();
  54.     }
  55. }

 

二、装饰设计模式

当对一组对象的功能进行增强时,就可以使用该模式进行问题的解决,上述的自定义MyBufferedReader类就是很好的体现,对于FileReader类比原来的功能简便,当然上述代码写的比较简单

 

  1. class Room{
  2.     public void show(){
  3.         System.out.println(“房子”);
  4.     }
  5. }
  6. class NewRoom
  7. {
  8.     private Room or;
  9.     public NewRoom(OldRoom or) {
  10.         // TODO Auto-generated constructor stub
  11.         this.or = or;
  12.     }
  13.     public void show(){
  14.         or.show();
  15.         System.out.println(“平房”);
  16.     }
  17. }

一定要避免的是修改源代码,当然继承也可以实现功能的增强。

 

但是继承的话,会让继承体系复杂且麻烦

 


装饰设计模式和继承的区别:

继承:如果为了增强功能,就要继续写子类,只是为了一个新的NewRoom,就要创建一个子类,NewRoom后出现别墅呢,又要创建子类,逐渐的,导致继承体系越来越臃肿

装饰设计模式:无论NewRoom还是别墅,都是Room的一种,都保持着房子的基本属性

所以,利用装饰设计模式,只需要把被装饰的对象传入即可,可以将缓冲技术单独抽取进行封装,要缓冲区谁将谁和缓冲相关联即可,这样的设计的相对体系会变的简单。

 

三、LineNumberReader

API文档解释:跟踪行号的缓冲字符输入流。此类定义了方法setLineNumber(int) 和 getLineNumber(),它们可分别用于设置和获取当前行号。

 

  1. import java.io.*;
  2. public class Main
  3. {
  4.     public static void main(String[] args) throws IOException {
  5.         FileReader fr = new FileReader(“ACM.txt”);
  6.         LineNumberReader lr = new LineNumberReader(fr);
  7.         String str = null;
  8.         lr.setLineNumber(10);//设置行号从10开始
  9.         while((str = lr.readLine())!=null){
  10.             System.out.println(str+” line : ”+lr.getLineNumber());
  11.         }
  12.         lr.close();
  13.     }
  14. }

此类用的地方不是很多,知道怎么用即可。

 

 

四、练习

一定要用字节流文件复制媒体文件

 

  1. import java.io.*;
  2. public class Main
  3. {
  4.     public static void main(String[] args) throws IOException {
  5.         //copy_mp3_1();
  6.         //copy_mp3_2();//开发建议使用这种
  7.         copy_mp3_3();
  8.     }
  9.     public static void copy_mp3_3() throws IOException {
  10.         // TODO Auto-generated method stub
  11.         FileInputStream fis = new FileInputStream(“D:\\盛夏光年.mp3″);
  12.         FileOutputStream fos = new FileOutputStream(“D:\\盛夏光年3.mp3″);
  13.         byte[] by = new byte[fis.available()];//局限:文件过大,就不行了
  14.         fis.read(by);
  15.         fos.write(by);
  16.         fos.close();
  17.         fis.close();
  18.     }
  19.     public static void copy_mp3_2() throws IOException {
  20.         // TODO Auto-generated method stub
  21.         FileInputStream fis = new FileInputStream(“D:\\盛夏光年.mp3″);
  22.         BufferedInputStream br = new BufferedInputStream(fis);
  23.         FileOutputStream fos = new FileOutputStream(“D:\\盛夏光年2.mp3″);
  24.         BufferedOutputStream bw = new BufferedOutputStream(fos);
  25.         int len = 0;
  26.         while((len = br.read())!=-1){
  27.                 bw.write(len);
  28.                 bw.flush();
  29.         }
  30.         br.close();
  31.         bw.close();
  32.     }
  33.     public static void copy_mp3_1() throws IOException {
  34.         // TODO Auto-generated method stub
  35.         FileInputStream fis = new FileInputStream(“D:\\盛夏光年.mp3″);
  36.         FileOutputStream fos = new FileOutputStream(“D:\\盛夏光年1.mp3″);
  37.         byte[] by = new byte[1024];//注意Mp3文件的字节数,这个数组越接近效率越块
  38.         int len = 0;
  39.         while((len = fis.read(by))!=-1){
  40.                 fos.write(len);
  41.                 fos.flush();
  42.         }
  43.         fos.close();
  44.         fis.close();
  45.     }
  46. }