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(); //换行就打印
else
sb.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
LineNumberReader是BufferedReader的子类。
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());
}
}
}
}
运行结果: