您的位置:首页 > 职场人生

黑马程序员_I/O流(字符流)

2013-04-28 20:58 309 查看
---------- android培训java培训、java学习型技术博客,期待与您交流!----------

        字符流具有两个基类:Reader和Writer。字符流中拥有专门操作文件的子类对象:FileReader和FileWriter。在新建FileWriter对象时,如果要写入的File对象在文件夹下有同名对象存在,则需要给新建的FileWriter对象传递一个true参数实现在已有文件末尾处进行续写,否则已有文件将被新建的File对象覆盖,数据也从开始处重新写入。FileReader对象读取文件数据有两种方法,一种是调用读取流对象的read方法,另一种则是自定义一个字符数组通过字符数组来读取。两种方法都以返回值-1来表示已达读取流末尾。

        为了提高流的操作效率就出现了缓冲区,既然缓冲区用于提高流的操作效率则在创建缓冲区之前必须先有流对象的存在。字符流的两个缓冲区子类对象即BufferedReader和BufferedWriter。其中BufferedWriter提供了一个跨平台的换行符功能:newLine;BufferedReader提供了一个一次读取一行数据的方法:readLine,这一方法方便了对于文本数据的获取。在BufferedReader中,readLine方法返回时只返回回车符之前的数据内容,并不返回回车符,并且其以返回null来表示读取到文件末尾。需要注意的是,只要用到缓冲区,就要记得刷新,即flush。如果文件数据不多,也可以直接通过close默认的关闭流前先刷新的特性来省略单独的flush步骤。

        查看源代码,明白了BufferedReader类中特有方法readLine的原理后,显而易见,我们自己也可以定义一个类中包含功能和readLine一致的方法,来模拟BufferedReader。代码如下:

import java.io.*;
class MyBufferedReaderDemo{
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("buf.txt");
MyBufferedReader myBuf = new MyBufferedReader(fr);
Sting line = null;
while((line=myBuf.myReadLine())!=null){
System.out.println(line);
}
myBuf.myClose();
}
}

class MyBufferedReader{
private Reader r;
MyBufferedReader(Reader r){
this.r = r;
}

//可以一次读一行数据的方法。
public String myReadLine() throws IOException {
//定义一个临时容器,原BufferedReader封装的是字符数组。
//为了演示方便就定义一个StringBuilder容器。因为最终还是要将数据变成字符串。
StringBuilder sb = new StringBuilder();
int ch = 0;
while((ch=r.read())!=-1){
if(ch=='\r')
continue;
if(ch=='\n')
return sb.toString();
else
sb.append((char)ch);
}
if(sb.length()!=0)
return sb.toString();
return null;
}
/*
覆盖Reader类中的抽象方法。
*/
public int read(char[] cbuf, int off, int len) throws IOException {
return read(cbuf,off,len);
}
public void close() throws IOException {
r.close();
}

public myClose() throws IOException {
r.close();
}
}
        这里就引出了java设计模式中的一种模式:装饰设计模式。装饰设计模式是指,当想要对已有对象进行功能增强时,可以定义类,将已有对象传入,基于已有对象的功能,并提供加强功能,自定义的该类称为装饰类。装饰类通常会通过构造方法接受被装饰的对象,并基于被装饰对象的功能提供更强的功能。

        不难发现,装饰设计模式和继承有相似之处,它所完成的功能继承也可以实现,那装饰设计模式有何存在的必要呢?假设以继承来实现功能的增强,可以模拟如下体系:

MyReader//专门用于读取数据的类。
|--MyTextReader
|--MyBufferTextReader
|--MyMediaReader
|--MyBufferMediaReader
|--MyDataReader
|--MyBufferDataReader

class MyBufferReader{
MyBufferReader(MyTextReader text){}
MyBufferReader(MyMediaReader media){}
...
}
        明显的,在这样的体系下,类的扩展性极差。找到其参数的共同类型,通过多态的形式可以提高扩展性。改变后如下:

class MyBufferReader extends MyReader {
private MyReader r;
MyBufferReader(MyReader r){}
}
体系变成:
MyReader//专门用于读取数据的类。
|--MyTextReader
|--MyMediaReader
|--MyDataReader
|--MyBufferReader
        可以得出结论,装饰设计模式比继承灵活,避免了继承体系的臃肿,同时也降低了类与类之间的关联性。此外,装饰类因为增强已有对象,具备的功能和已有对象是相同的,只不过提供了更强的功能。所以装饰类和被装饰类通常都属于一个体系中。

        基于装饰设计模式的学习和理解,跟踪行号的缓冲字符输入流LineNumberReader也就不难理解和自定义增强了。

---------- android培训java培训、java学习型技术博客,期待与您交流!----------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息