IO流二:IO流之缓冲区BufferedReader、BufferedWriter、装饰设计模式、LineNumberReader

来源:互联网 发布:咫尺网络 h5 编辑:程序博客网 时间:2024/05/17 03:59

1.  IO流之缓冲区:BufferedWriter

缓冲区的出现是为了提高流的操作效率。

所以在创建缓冲区之前,必须要先有流对象。

代码示例:

import java.io.*;class BufferedWriterDemo {public static void main(String[] args) throws IOException{//创建一个字符写入流对象。FileWriter fw = new FileWriter("buf.txt");//为了提高字符写入流的效率,加入了缓冲技术。//只要将需要被提高效率的流对象,作为参数传递给缓冲区的构造函数即可。创建指定流的缓冲区。BufferedWriter bufw = new BufferedWriter(fw);bufw.write("abcde"); //BufferedWriter是Writer的子类。bufw.newLine(); //缓冲区特有换行方法,此方法可以跨平台使用。bufw.write("newLine");//记住,只要用到缓冲区,就要记得刷新。bufw.flush();//其实关闭缓冲区,就是在关闭缓冲区中的流对象。关闭了缓冲区就是关闭了流。bufw.close();}}

2.  IO流之缓冲区:BufferedReader

该缓冲区提供了一个一次读一行的方法readLine(),方便对于文本数据的获取。

将这一行的数据以字符串形式返回,当返回null时,表示读到文件末尾。

代码示例:

import java.io.*;class BufferedReaderDemo {public static void main(String[] args) throws IOException{//创建一个读取流对象,冰河文件相关联。FileReader fr = new FileReader("buf.txt");//为了提高效率,加入缓冲技术。//将字符读取流对象,作为参数传递给缓冲区对象的构造函数。创建指定流的缓冲区。BufferedReader bufr = new BufferedReader(fr);String s1 = bufr.readLine();//读取文本的一行,以字符串形式返回。                            //readLine是缓冲区特有方法。System.out.println(s1);bufr.close();}}

3.  通过缓冲区复制一个java源文件

代码示例:

import java.io.*;class CopyTextByBufDemo {public static void main(String[] args){BufferedReader bufr = null;BufferedWriter bufw = null;try{bufr = new BufferedReader(new FileReader("BufferedWriterDemo.java"));bufw = new BufferedWriter(new FileWriter("bufWriter_copy.txt"));String line = null;while((line=bufr.readLine())!=null) {bufw.write(line);bufw.newLine(); //这里需要换行。bufw.flush();}}catch(IOException e){System.out.println(e.toString());}finally{try{if(bufr!=null)bufr.close();}catch(IOException e){System.out.println(e.toString());}try{if(bufw!=null)bufw.close();}catch(IOException e){System.out.println(e.toString());}}}}

4.  MyBufferedReader和装饰设计模式

自己使用read()实现一个BufferedReader

readLine()原理:readLine读取一行,其实也是逐个字符的读取,每读取一个就暂时存起来,遇到换行符再一次性打印出去,readLine就是用read实现的。

 

明白了BufferedReader类中特有方法readLine()的原理后,可以自定义一个类中包含一个功能和readLine一致的方法,来模拟一下BufferedReader

 

装饰设计模式:

当想要对已有的对象进行功能增强时,

可以定义一个类,将已有对象传入,基于已有功能,并提供加强功能。

那么自定义的该类成为装饰类。

装饰类通常会通过构造方法接收被装饰的对象。

并基于被装饰的对象的功能,提供更强的功能。

 

代码示例:

import java.io.*;class MyBufferedReader{private FileReader fr;//增强FileReader的功能,把它传入新的类。装饰设计模式。MyBufferedReader(FileReader fr){this.fr = fr;}//可以一次读一行数据的方法。public String myReadLine() throws IOException{//定义一个临时容器,原BufferedReader封装的是字符数组。//为了演示方便,定义一个StringBuiler容器。因为最终还是要将数据变成字符串。StringBuilder sb = new StringBuilder();int ch = 0;while((ch =fr.read())!=-1){if(ch=='\r')continue; //读最后一行时只有回车\r,没有换行\n,所以返回空,不打印。if(ch=='\n')return sb.toString(); //换行就打印elsesb.append((char)ch); //不换行就存储}if(sb.length()!=0)return sb.toString();return null;}public void myClose() throws IOException{fr.close();}}class MyBufferedReaderDemo{public static void main(String[] args) throws IOException{FileReader fr = new FileReader("buf.txt");MyBufferedReader myBuf = new MyBufferedReader(fr);String line = null;while((line=myBuf.myReadLine())!=null) {//读取一行System.out.println(line);}myBuf.myClose();}}

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

 

MyReader //专门用于读取数据的类

        |--MyTextReader

                |--MyBufferTextReader

        |--MyMediaReader

                |--MyBufferMediaReader

        |--MyDataReader

                |--MyBufferDataReader

 

装饰的过程:

class MyBufferTextReader extends MyTextReader{MyBufferTextReader(MyTextReader text){ }}class MyBufferMediaReader extends MyMediaReader{MyBufferMediaReader(MyMediaReader text){ }}class MyBufferDataReader extends MyDataReader{MyBufferDataReader(MyDataReader text){ }}

上面这个体系扩展性很差,需要增加新的功能对象时,就需要增加新的带缓冲的子类,非常臃肿,

找到其参数的共同类型。通过多态的形式。可以提高扩展性。

 

装饰设计模式优化后:

 

MyReader //专门用于读取数据的类

        |--MyTextReader

        |--MyMediaReader

        |--MyDataReader

        |--MyBufferReader

 

//装饰的结果:

class MyBufferReader extends MyReader {MyBufferReader(MyReader r){ }MyBufferReader(MyTextReader r){ }MyBufferReader(MyMediaReader r){ }MyBufferReader(MyDataReader r){ }}

装饰设计模式比继承要灵活,避免了继承体系臃肿。

而且降低了类与类之间的关系。

装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强功能。

所以装饰类和被装饰类通常都属于一个体系中。

 

6.  跟踪行号的缓冲读取流:LineNumberReader

LineNumberReaderBufferedReader的子类。

 

getLineNumber():获得当前行号。

setLineNumber(int):设置当前行号。

 

代码示例:

import java.io.*;class LineNumberReaderDemo {public static void main(String[] args){FileReader fr = null;LineNumberReader lnr =null;try{fr = new FileReader("Demo.java");lnr = new LineNumberReader(fr);String line = null;lnr.setLineNumber(100); //设置当前行号。while((line=lnr.readLine())!=null){ //获取当前行号。System.out.println(lnr.getLineNumber()+"::"+line);}}catch(IOException e){System.out.println(e.toString());}finally{if(lnr!=null)try{lnr.close();}catch(IOException e){System.out.println(e.toString());}}}}

运行结果:



0 0