io流(二)

来源:互联网 发布:蓝月传奇羽毛进阶数据 编辑:程序博客网 时间:2024/05/22 16:52

处理流:

处理流可以隐藏底层设备上节点流的差异,并对外提供更加方便的输入输出方法,只要关心高级流的操作方法。
使用处理流的典型思路是,使用处理流来包装节点流,程序通过处理流来执行输入输出功能,让节点流与底层的I/O设备、文件交互。
识别处理流非常简单,只要流的构造器参数不是一个物理的节点,而是已经存在的流,那么这种流就一定是处理流。而所有的节点流都是直接以物理IO节点为构造器参数的。

下面使用BuffeReader复制一个文件。BufferReader中提供了一个readLine()的方法可一非常方便的回去文件。
<span style="font-size:14px;">public class CopyTextByBuf {public static void main(String[] args) {BufferedReader br = null ;BufferedWriter bw = null ;try {//创建BufferedReader对象,将FileReader字符流当参数传递进去br = new BufferedReader(new FileReader("g:\\test.txt"));bw = new BufferedWriter(new FileWriter("g:\\testCopy.txt"));String line ;//使用BufferedReader的readLine()方法一次读一行//readLine()返回的字符串是不包含换行符的。//当读到文件结尾的时候返回nullwhile((line=br.readLine())!=null){bw.write(line);//通过newLine向输出流中写入一个换行符。bw.newLine();//BufferWriter中带有缓冲区,输出时要刷新。bw.flush();}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}finally{if(br!=null){try {br.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}if(bw!=null){try {bw.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}}</span>


自定义一个类实现BufferReader()中的readLine()方法

readLine () 原理:实际上是调用了传进来的字符流的read()方法,每次只读一个字符,然后将读的字符存在自己的缓冲区中。当读到换行的时候将缓冲区中的字符一起输出。
public class CopyTextByBuf {public static void main(String[] args)throws IOException {MyBufferedReader br = null ;br = new MyBufferedReader(new FileReader("g:\\test.txt"));String line ;while((line=br.myReadLine())!=null){System.out.println(line);}br.myClose();}}/* * 自定义的BufferReader */class MyBufferedReader{Reader r ;//构造MyBufferReader是需要将一个Reader传递进去public MyBufferedReader(Reader reader){r = reader ;}//使用StirngBuilder当作缓冲区//当没有读到换行符号的时候每读一个字符就往缓冲区中放//当读到换行符时,将缓冲区中的字符一起输出public String myReadLine() throws IOException{int ch =0;StringBuilder sb = new StringBuilder();while((ch=r.read())!=-1){//windows 中换行符是两个字符组成//读第一个时,直接跳出循环,再往下读if((char)ch=='\r')continue;//读到换行符的末尾时输出if((char)ch =='\n')return sb.toString();else sb.append((char)ch);}if(sb.length()!=0){return sb.toString();}return null ;}//关闭流操作,直接关闭reader流。//在后面使用中就不用调用reader的close方法了public void myClose()throws IOException{r.close();}}

使用LineNumberReader现实每行的行号:

public class LineNumberReaderTest {public static void main(String[] args) throws IOException{//创建LineNumberReader对象LineNumberReader lr = new LineNumberReader(new FileReader("g:\\test.txt"));String str = null ;//设置从11行开始读lr.setLineNumber(10);while((str=lr.readLine())!=null){//通过getLineNumber拿到行号System.out.println(lr.getLineNumber()+":"+str);}//关闭流lr.close();}}<strong></strong>

自定义一个类实现LineNumberReader的getLineNumber()方法。
public class LineNumberReaderTest {public static void main(String[] args) throws IOException{//创建MyLineNumberReader对象MyLineNumberReader lr = new MyLineNumberReader(new FileReader("g:\\test.txt"));String str = null ;while((str=lr.myReadeLine())!=null){//通过myReadeLine拿到行号System.out.println(lr.myGetlineNumber()+":"+str);}//关闭流lr.myClose();}}class MyLineNumberReader{Reader r ;int lineNumber  ;public MyLineNumberReader(Reader reader){r = reader ;}public String myReadeLine()throws IOException{StringBuilder buf = new StringBuilder() ;int ch = 0 ;while((ch = r.read())!=-1){if(ch =='\r')continue;if(ch=='\n'){//当读到一行的末尾时,行号加一。lineNumber++;return buf.toString();}else buf.append((char)ch);}if(buf.length()!=0){//当结尾不是以换行结束在返回字符串是行号加一。lineNumber++;return buf.toString();}return null ;}public int myGetlineNumber(){return lineNumber ;}public void myClose()throws IOException{r.close();}}

装饰设计模式:

当想要对已有的对象进行功能加强时,可以定义一个类,将已有的对象传入,基于已有的功能并提供加强功能。自定义的类称为装饰类。
装饰类通常会通过构造方法接受被装饰的对象,并基于被装饰的对象进行功能的加强。

  • 通过继承可以实现讲一个类的功能进行加强
MyReader :专门用于读取数据的类
| --MyTextReader
| --MyBufferTextReader
| --MyMediaReader
| --MyBufferMediaReader
| --MyDataReader
| --MyBufferDataReader
通过继承实现,展现性不好,继承关系复杂。对不同的类增加相同的功能时,每个都要添加,添加的代码还是一样的。

  • 通过继承可以实现讲一个类的功能进行加强
MyReader :专门用于读取数据的类
| --MyTextReader
| --MyMediaReader
| --MyDataReader
| --MyBufferReader
装饰模式比继承要灵活,避免了继承关系的臃肿,而且降低了类与类之间的关系。
装饰类因为只是增强已有的对像,具有的功能和已有的功能相同,只是提供了更强的功能。所以装饰类和被装饰类通常位于一个体系中。
public class PersonTest {public static void main(String[] args) {// TODO Auto-generated method stubSuperPerson person1 =new SuperPerson(new Person());person1.chifan();SuperPerson2 person2 = new SuperPerson2() ;person2.chifan();}}class Person{public void chifan(){System.out.println("吃饭");}}//采用装饰的方式增强Person类class SuperPerson{Person p ;public SuperPerson(Person p){this.p = p ;}public void chifan(){System.out.println("开胃酒") ;p.chifan();System.out.println("甜点");}}//采用继承的方式增强Person类class SuperPerson2 extends Person{public void chifan(){System.out.println("开胃酒") ;super.chifan();System.out.println("甜点");}}


自定一个读取缓冲区类,模拟一个BufferReader

分析:缓冲区中封装了一个数组,并对外提供了更多的方法会数组进行访问,其实这些方法最终操作的都是数组的角标。
缓冲原理:从源中获取一批数据到缓冲区中,再从缓冲区中不断地取出一个一个数据,当缓冲区中的数据取完了,再从源中缓存一批数据到缓冲区中。当数据取完是返回-1.

public class MyBufferReaderTest {public static void main(String[] args)throws IOException{MyBufferReader mr = new MyBufferReader(new FileReader("g:\\test.txt"));String str =null ;while((str=mr.myReadLine())!=null){System.out.println(str);}}}class MyBufferReader{Reader r ;//定义一个数组最为缓冲区char[] buf = new char[1024] ;public MyBufferReader(Reader r){this.r = r ;}//定义count保存每次读取字符的个数,表示可以读的个数。index为数组的下表int count ,index ;public int myRead() throws IOException{//当count为0时从源中读取数据,将读取个数放到count中,//将数组游标清0; if(count ==0){count = r.read(buf) ;index =0;return buf[index];} //当count==-1是表示已经读到末尾了 if(count ==-1){ return -1 ; } //每读一次,游标向下移动一次,可读个数减1. char c = buf[index]; count--; index++; return c ;}public String myReadLine()throws IOException{StringBuilder buf = new StringBuilder();int ch ;while((ch=myRead())!=-1){if(ch=='\r')continue ;if(ch=='\n')return buf.toString();elsebuf.append((char)ch);}if(buf.length()!=0){return buf.toString();}return null;}}




0 0
原创粉丝点击