字符流的缓冲区

  • 缓冲区的出现提高了对数据的读写效率。
  • 对应类:
    •   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. Apache配置HTTPS协议搭载SSl配置全过程

    1.首先要开启相应的扩展和辅助的dll(ssleay32.dll,libeay32.dll)到system32下 2.生成服务器证书 安装好在bin目录下有一个openssl.exe文件,用来生成证书 ...

  2. TinyXml快速入门(一)

    对于xml文件,目前的工作只是集中在配置文件和作为简单的信息文件来用,因此我不太喜欢使用msxml这种重量级的xml解析器,特别是使用msxml解析xml涉及到复杂的com类型转换,更是令人感觉繁琐. ...

  3. Linux crontab 命令详解(含配置文件路径)

    编辑/etc/crontab 文件配置cron cron 服务每分钟不仅要读一次/var/spool/cron内的所有文件,还需要读一次/etc/crontab,因此我们配置这个文件也能运用cron服 ...

  4. Java基础知识强化28:Scanner类之Scanner类的概述

    1.Scanner概述:         JDK5以后用于获取用户的键盘输入 2.Scanner的构造方法:         public Scanner (InputStream  source) ...

  5. Oracle Linux 挂载存储

    #启动多路径multipathd服务 service multipathd restart #设置开机自动启动multipathd服务 chkconfig multipathd on #查看信息mul ...

  6. VS快速定位文件、代码插件——DPack

    之前用Myeclipse开发一个Java项目,发现其中“Open Resource”(Ctrl+Shirft+R)的功能比较好用,回到.Net后就找了找VS相应的功能,试了几个后觉得Dpack比较好用 ...

  7. 网页上facebook分享功能的具体实现

    1,一个链接: 参数是要分享的页面的链接 代码如下: <a style="width:35px; height:40px; position:relative; top:10px; l ...

  8. Oracle数据库名、实例名、数据库域名、全局数据库名、服务名之间的区别

    数据库名.实例名.数据库域名.全局数据库名.服务名 这是几个令很多初学者容易混淆的概念.相信很多初学者都与我一样被标题上这些个概念搞得一头雾水.我们现在就来把它们弄个明白. 一.数据库名 什么是数据库 ...

  9. dom方法读取xml(不常用)

    Book.java package com.xml.demo; public class Book { private int id; private String name; private Flo ...

  10. C# 截取字符串,区分中英文情况

    public static string SubstringByCN(string strInput, int begin, int length) { if (!Regex.IsMatch(strI ...