IO(二)Buffered流以及装饰模式



BufferedReader和BufferedWriter分别是Reader和Writer的直接子类。他们称为字符流的缓冲区。
BufferedInputStreamBufferedOutputStream分别是FilterInputStream的直接子类FilterOutputStream他们称为字节流的缓冲区。

 

 

缓冲区的出现提高了流对数据的读写效率。缓冲区是为流服务的谁在创建缓冲区之前必须流对象。

BufferedReader中的特殊方法:

public void newLine()写入一个行分隔符
BufferedWriter中的特殊方法:
public String readLine()读入一个文本行,并以字符串返回。
此方法可以用来作为循环结束的条件readLine()!=null,等于空时表示已读到文件尾了,之一此方法读取一行后返回的String不包含回车符
此方法的原理:无论是读一行或者读取多个字节,其实最终都是在硬盘上一个一个的读取,所以最终使用的还是read()方法此方法只是在内存中开辟了一个数组,并将每次读取的数据存入此数组,当读到’\r’,’\n’时,表示该行结束,此时将此数组转成String返回,方法就结束了。Readline方把’\r’,’\n’作为行的结束,并且不会读取。

装饰设计模式:

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

装饰和继承的区别:

装饰模式要比继承灵活,避免了继承的臃肿。而且降低了类与类之间的关系。

装饰类因为增强已有类的功能,几倍的功能和已有功能相同,只不过提供了更强大的功能。所以装饰类和被装饰类通常都是输同一个体系的,结成统一个类或者接口,这种结构称为组合结构(装饰模式将继承转成组合结构)。

需求:1.自定义一个字符流的缓冲区,更BufferedReader具备相同的工能即ReadLIne方法

 /*
自定义一个缓冲流类与BufferedReader具有相似功能
装饰模式的应用


*/


import java.io.*;


class MyBufferedReaderextends Reader {
private FileReader fr;

public MyBufferedReader(FileReader fr)throws IOException{
this.fr = fr;
}

public String MyReadLine()throws IOException{
int x = 0;
StringBuilder sb = new StringBuilder();
while((x = fr.read()) != -1){
if(x == '\n' || x == '\r'){
return  sb.toString();
}else{
sb.append((char)x);
}
}
 if(x == -1)
  return null;
return sb.toString();
}

public void close()throws IOException{
fr.close();
}

public int read(char[] cbuf,int off,int len)throws IOException{
return fr.read(cbuf,off,len);
}



}


class MyBufferedReaderDemo{
public static void main(String[] args)throws IOException{
MyBufferedReader mbr = new MyBufferedReader(new FileReader("MyBufferedReaderDemo.java"));
String str = null;
while((str = mbr.MyReadLine()) != null){
System.out.println(str);

}
mbr.close();
}
}

 

LineNumberReaderBufferedReade的直接子类,特有方法
public int getLineNumber()获得当前行号。

public void setLineNumber(int lineNumber)设置当前行号。如果不设置的话,默认从0开始,设置的是几就从几开始

 

需求:2.自定义一个字符流,LineNumberReader具备相同的工能即ReadLIne方法

 /*
模拟一个带行号的缓冲区
优化改进后的
*/


import java.io.*;


class MyLineNumberReader extends MyBufferedReader{
	private int lineNumber = 0;
	
	public MyLineNumberReader(FileReader fr)throws IOException{
		super(fr);
	}
	
	public String MyReadLine()throws IOException{
		lineNumber++;
		return super.MyReadLine();
	}
	
	
	//获得当前行号。
	public int getLineNumber(){
		return lineNumber;
	}
	
	//设置当前行号。 
	public void setLineNumber(int lineNumber){
		this.lineNumber = lineNumber;
	}
}


class  MyLineNumberReaderDemo1{
 public static void main(String[] args){
 	MyLineNumberReader lnbr = null;
 	try{
 		//建立一个行号造作流,并传入一个流对象
 		lnbr = new  MyLineNumberReader(new FileReader("LineNumberReaderDemo.java"));
 		String str = null;
 		lnbr.setLineNumber(5);//设置起始行号,默认是从1开始
 		while((str = lnbr.MyReadLine()) != null){
 			//获得行号并打印行号
 			System.out.println(lnbr.getLineNumber()+ "::"+str);
 		}
 	}catch(FileNotFoundException e){
 		throw new RuntimeException(" can mot found file");
 	}catch(IOException e){
 		throw new RuntimeException(" read fail");
 	}finally{
 		try{
	 		if(lnbr != null)
	 		lnbr.close();//关闭流资源
	 	}catch(IOException e){
	 		 
	 	}
 	}
 }
}


 

字节流在readwrite是的特点read()方法每次读取的是一个字节但返回的却是一个Int的数据,所以此方法byte进行过了类型提升,而writeint)方法只是将int型的低八位写入。

在用键盘录入时,为什么只录入一个字符会打印三个值呢?

因为有回车符:“\r\n,’\r’=13, ’\n’=10

在用键盘录入时,发现其实就是读一行的原理。那么能不能用ReadLIne方法来完成键盘的录入呢?readerLine是字符流BufferedReader的方法,而标准输出流是字节流,所以此时要用到转换流。InputStreamReader 和InputStreamReader是Reader和Writer的直接子类

 

 

 

BufferedReader in =
New BufferedReader(new InputStreamReader(System.in));
 
Writer out
   = new BufferedWriter(new OutputStreamWriter(System.out));
那么什么时候使用转换流呢?
转换流是字符流和字节流之间的桥梁,通常涉及到字符编码的时候,
需要用到转换流
System类中的静态方法
public static void setIn(InputStream in)
public static void setOut(PrintStream out)

可以让我们自己设定标准输入输出流

 


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值