io流(二)

处理流:

处理流可以隐藏底层设备上节点流的差异,并对外提供更加方便的输入输出方法,只要关心高级流的操作方法。
使用处理流的典型思路是,使用处理流来包装节点流,程序通过处理流来执行输入输出功能,让节点流与底层的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()返回的字符串是不包含换行符的。
			//当读到文件结尾的时候返回null
			while((line=br.readLine())!=null){
				bw.write(line);
				//通过newLine向输出流中写入一个换行符。
				bw.newLine();
				//BufferWriter中带有缓冲区,输出时要刷新。
				bw.flush();
			}
		
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			if(br!=null){
				try {
					br.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
			if(bw!=null){
				try {
					bw.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.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 stub
		SuperPerson 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();
			else
				buf.append((char)ch);
		}
		
		if(buf.length()!=0){
			return buf.toString();
		}
		return null;
	}
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值