字符流的缓冲区

  • 缓冲区的出现提高了对数据的读写效率。
  • 对应类:
    •   BufferedWriter
    • BufferedReader
  • 缓冲区要结合流才可以使用。
  • 在流的基础上对流的功能进行了增强。

BufferedWriter

将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。

缓冲区的出现是为了提高流的操作效率而出现的。所以在创建缓冲区之前,必须要先有流对象。

void newLine():写入一个行分隔符。(跨平台换行符)

import java.io.*;

class BufferedWriterDemo
{
pubilc static void main(String[] args)Throws IOException
{
//创建一个字符写入流对象。
FileWriter fw = new FileWriter("buf.txt"); //为了提高字符流写入效率,加入了缓冲技术。原理:对象里面封装了数组。只要将需要被提高效率的流对象作为参数传递给缓冲区的构造函数即可。
BufferedWriter bufw = new BufferedWriter(fw); buyw.write("abcde"); //记住,只要用到缓冲区,就要记得刷新。
bufw.flush(); //其实关闭缓冲区,就是在关闭缓冲区的流对象。
bufw.close(); } }

BufferedReader

从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。

String readLine():读取一个文本行。(该缓冲区提供了一个一次读一行的方法,方便与对文本数据的获取。当返回null时,表示读到文件末尾。

import java.io.*;

class BufferReaderDemo
{
pubic static void main(String[] args)
{
//创建一个读取流对象与文件相关联。
FileReader fr = new FileReader("buf.txt"); //为了提高效率,加入缓冲技术,将字符读取流对象作为参数传递给缓冲对象的构造函数。
BufferedReader bufr = new BufferedReader(fr); String line = null; while((line=bufr.readLIne()) !null)
{
System.out.pritnln(line);
} bufr.close(); } }

通过缓冲区复制文本文件

练习:通过缓冲区复制一个.java文件。

readLine方法返回的时候只返回回车符之前的数据内容。并不返回回车符。

readLine方法原理:无论是读一行,获取读取多个字符,其实最终都是在硬盘上一个一个读取,所以最终使用的还是read方法,一次读一个的方法。

import java.io.*;

class CopyTestByBuf
{
public static void main(String[] args)
{
BufferReader bufr = null;
BufferWriter bufw = null;
try
{
bufr = new BufferReader(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.fiush(); }
ctach(IOException e)
{
throw new RuntimeException("读写失败");
} finally
{
try
{
if(bufr!=null)
bufr.close();
}
catch(IOException e)
{
throw new RuntimeException("读取关闭失败");
}
try
{
if(bufw!=null)
bufw.close();
}
catch(IOException e)
{
throw new RuntimeException("写入关闭失败");
}
} }
} }

myBufferedReader

明白了BufferedReader类中特有方法readLine的原理后,可以自定义一个类中包含一个功能和readLine一致的方法。来模拟一下BufferedReader。

import java.io.*;

class MyBufferedReader
{
private FileReader r;
MyBufferedReader(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;
}
pubilc void myClose()throws IOException
{
r.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 = myReadLine())!=null)
{
System.out.println(line);
}
muBuf.mtClose(); } }

装饰设计模式

由上述例子可见,readLine()方法是在增强read()方法,通过将被增强的对象传给增强类,提供了一个基于它的读一行的方法,MyBufferedReader其实就是在对FlieReader进行增强,那么这种方式我们也把它称之为一种设计模式,叫做装饰设计模式。 

装饰设计模式:当想要对已有对象进行功能增强时,可以定义类,将已有对象传入,基于已有功能,并提供加强功能,那么自定义的该类称为装饰类。 

装饰类通常会通过构造方法接收被装饰对象并基于被装饰的对象的功能,提供更强的功能。

class Person
{
public void chifan()
{
Systam.out.println("吃饭");
}
} class SuperPerson
{
private Person p;
SuperPerson(Person P)
{
this.p = p;
}
public void superChifan()
{
Systam.out.println("开胃酒");
p.chifan();
Systam.out.println("甜点");
Systam.out.println("来一根"); }
} class PersonDemo
{
public static void main(String[] args)
{
Person p = new Person();
SuperPerson sp = new SuperPerson(p); sp.superChifan();
} }

装饰和继承的区别

MyReader//专门用于读取数据的类。

  |--MyTextReader

    |--MyBufferTextReader

  |--MyMediaReader

    |--MyBufferMediaReader

  |--MyDateReader

    |--MyBufferDateReader

继承体系虽然能用,但是扩展性非常不好,体系臃肿。需要进行优化,发行着三个类扩展出来的都是同一种技术,所以单独定义一个缓冲类MyBufferReader。

class MyBufferReader

{

MyBufferReader(MyTextReader text)

{}

MyBufferReader(MyMediaReader media)

{}

}

上面这个类扩展性很差,找到其参数的共同类型,通过多态的形式,可以提高扩展性。

class MyBufferReader extends MyReader

{

private MyReader r ;

MyBufferReader(MyReader r)

{

this.r = r;

}

}

优化后体系:

MyReader

  |--MyTextReader

  |--MyMediaReader

  |--MyDateReader

  |--MyBufferReader

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

装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强的功能,所以装饰类和被装饰类通常都是属于同一个体系中。(所属同一个父类或者同一个接口)

自定义装饰类

import java.io.*;

class MyBufferedReader extends Reader
{
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
{
r.read(cbuf,off,len);
} public void close()throws IOException
{
r.close();
} pubilc void myClose()throws IOException
{
r.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 = myReadLine())!=null)
{
System.out.println(line);
}
muBuf.mtClose(); } }

LineNumberReader装饰类

LineNumberReader:跟踪行号的缓冲字符输入流。此类定义了方法 setLineNumber(int)getLineNumber(),它们可分别用于设置和获取当前行号。

import java.io.*;

class LineNumberReaderDemo
{
publiv static void main(String[] args)throws IOException
{
FileReader fr = new FileReader("PersonDemo.java");
LineNumberReader lnr = new LineNumberReader(fr); String line = null;
lnr.setLineNumber(100); while((line= lnr.readline())!=null)
{
System.out.println(lnr.getLineNumber+":"+line);
} lnr.close();
} }

练习:模拟一个带行号的缓冲区对象。

MyLIneNumberReader

import java.io.*;

class MyLineNumberReader extends myBufferedReader
{
private int lineNumber;
MyLineNumberReader(Reader r)
{
super(r);
} public String myReadline()
{
lineNumber++;
super myReadLine();
} public int setLineNumber(int lineNumber)
{
this.lineNumber = lineNumber;
} public int getLineNumber()
{
return lineNumber;
}
} /* class MyLineNumberReader
{
private Reader r;
private int lineNumber;
MyLineNumberReader(Reader r)
{
this.r = r;
} public String myReadline()
{
lineNumber++;
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;
} public int setLineNumber(int lineNumber)
{
this.lineNumber = lineNumber;
} public int getLineNumber()
{
return lineNumber;
}
public void myClose()
{
r.close();
}
}
*/ class MyLineNumberReaderDemo
{
public static void main(String[] args)throws IOException
{
FileReader fr = new FileReader("copyTextByBuf.java)
MyLIneNumberReader mylnr = new MyLIneNumberReader(fr); Stirng line = null; mylnr.setLineNumber(100); while((line = mylnr.myReadLine())!null)
{
System.out.println(mylnr.getLineNumber+"::"+line);
}
mylnr.myClose();
}
}

。。。。。。

黑马程序员_JavaIO流(二)的更多相关文章

  1. 黑马程序员_JavaIO流(四)

    File概述 File类 用来将文件或者文件夹封装成对象. 方便对文件与文件夹的属性信息进行操作. File对象可以作为参数传递给流的构造函数. 了解File类中的常用方法. 字段:static St ...

  2. 黑马程序员_JavaIO流(一)

    IO(Input Output)流 概述: IO流(数据流)用来处理设备之间的数据传输. Java对数据的操作是通过流的方式. Java用于操作流的对象都在IO包中. 流按操作数据分为两种:字节流与字 ...

  3. 黑马程序员_JavaIO流(三)

    字节流File读写操作 字符流: FileReader FileWriter BufferedReader BufferedWrtier 字节流: FileInputStream FileOutput ...

  4. 黑马程序员-IO(二)

    ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 装饰设计模式: 当想要对已有对象进行功能增强时.可以定义类,将已经有的类传入,基于已经有的功能, ...

  5. 黑马程序员-集合(二)contains()方法的内部探索

    ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 我们知道集合是用来存储对象的.在他们实现了众多的接口我们以Arraylist为列子 所有已实现的 ...

  6. 黑马程序员——【Java高新技术】——代理

    ---------- android培训.java培训.期待与您交流! ---------- 一.“代理概述”及“AOP概念” (一)代理概述 1.问题:要为已存在的多个具有相同接口的目标类的各个方法 ...

  7. 黑马程序员:轻松精通Java学习路线连载1-基础篇!

    编程语言Java,已经21岁了.从1995年诞生以来,就一直活跃于企业中,名企应用天猫,百度,知乎......都是Java语言编写,就连现在使用广泛的XMind也是Java编写的.Java应用的广泛已 ...

  8. 黑马程序员:3分钟带你读懂C/C++学习路线

    随着互联网及互联网+深入蓬勃的发展,经过40余年的时间洗礼,C/C++俨然已成为一门贵族语言,出色的性能使之成为高级语言中的性能王者.而在今天,它又扮演着什么样重要的角色呢?请往下看: 后端服务器,移 ...

  9. 【黑马18期Java毕业生】黑马程序员Java全套资料+视频+工具

        Java学习路线图引言:        黑马程序员:深知广大爱好Java的人学习是多么困难,没视频没资源,上网花钱还老被骗. 为此我们历时一个月整理这套Java学习路线图,不管你是不懂电脑的小 ...

随机推荐

  1. jQuery.each() 的5个案例

    1.基本的jQuery.each实例 看看 each() 函数是如何处理一个 jQuery 对象的.首先选取所有的a标签 并且打印出他们的href属性. 需要注意的是, 在 each() 当中使用 j ...

  2. css07家用电器分类

    1.创建一个html页面 <!DOCTYPE html> <html> <head lang="en"> <meta charset=&q ...

  3. JavaBean-Servlet-JavaServerPage(转)

    1.servlet servlet是在服务器端执行的,具有良好的移植性,不论操作系统是Windows.Linux.Unix等等,都能将写好的Servlet程序放在这些操作系统上执行,是真正的写一次,到 ...

  4. phpMyAdmin配置及 错误 缺少 mysqli 扩展。请检查 PHP 配置

    PHPMyadmin配置文件config.inc.php内容如下,在需要设置的地方增加了相关注释.     非常适合对数据库操作命令不熟悉的数据库管理者,下面我就说下怎么安装该工具: 1.先到网上下载 ...

  5. 关于服务器防火墙和discuz论坛的问题

    今天做了一个b2b商城,其中的论坛用的是discuz论坛 .net版本,主页要取出其中三个板块的最新帖子数据,安装好后,帖子数据在dnt_posts1数据表里,其中的tid为外链表dnt_forums ...

  6. ORACLE日期加减【转】

    首先,感谢这个作者的辛勤汗水给我们带来的总结,因为日期函数操作对平时的使用真的是很常用,所以收藏一下以作后期使用. 原贴地址:http://www.cnblogs.com/xiao-yu/archiv ...

  7. UIVIew之霓虹灯实现

    // // AppDelegate.m // NiHongPractice // #import "AppDelegate.h" #define kColorValue arc4r ...

  8. 武汉科技大学ACM :1010: 零起点学算法12——求2个日期之间的天数

    Problem Description 水题 Input 输入2个日期,日期按照年月日,年月日之间用符号-隔开(题目包含多组数据) Output 求出这2个日期之间的天数(不包括自身),每组测试数据一 ...

  9. [转]《深度探索C++对象模型》读书笔记[一]

    前 言 Stanley B.Lippman1.   任何对象模型都需要的三种转换风味: ü        与编译器息息相关的转换 ü        语言语义转换 ü        程序代码和对象模型的 ...

  10. php微信简单接口

    <?php $appid = "xxxxxxxxxx"; $secret = "xxxxxxxxxxxxxxxxxxxxxxxxx"; $url = &q ...