1.缓冲区的出现是为了提高读写效率。
2.字符流缓冲区
BufferedWriter:
将文本写入字符输出流,缓冲各个字符,
从而提供单个字符、数组和字符串的高效写入。
特有方法:newline();//分行
BufferedReader:
从字符输入流中读取文本,缓冲各个字符,
从而实现字符、数组和行的高效读取。
特有方法:readLine();//读取一行数据,当下一行没有数据时返回null。
//利用缓冲区读写的基本操作
private static void demo1() throws IOException {
//创建了一个输出流对象并关联了一个buf1.txt文件
FileWriter fw = new FileWriter("buf1.txt");
//为了提高写入的效率,创建了一个字符流的缓冲区,并和要缓冲的输出流对象产生关联。
BufferedWriter bufw = new BufferedWriter(fw);
for (int i = 0; i < 10; i++) {
bufw.write("haha"+i);
//分行符
bufw.newLine();
//利用缓冲区的刷新方法,将数据刷到目的地中。
bufw.flush();
}
//关闭缓冲区实质上是关闭了流对象
bufw.close();
}
private static void demo2() throws IOException {
//创建一个输入数据流对象
FileReader fr = new FileReader("buf1.txt");
//为了提高输入效率,创建缓冲区对象,并和指定要缓冲的输入流对象关联。
BufferedReader bufr = new BufferedReader(fr);
String line ;
while ((line = bufr.readLine())!=null){
System.out.println(line);
}
char[] buf = new char[1024];
int len;
while ((len = bufr.read(buf))!=-1){
System.out.println(new String(buf,0,1024));
}
bufr.close();
}
3.利用缓冲区实现文本的复制功能。
private static void demo2() {
FileReader fr = null;
BufferedReader bufr = null;
FileWriter fw = null;
BufferedWriter bufw = null;
try {
fr = new FileReader("buf1.txt");
bufr = new BufferedReader(fr);
fw = new FileWriter("Copybuf1.txt");
bufw = new BufferedWriter(fw);
String line;
while ((line = bufr.readLine())!=null){
bufw.write(line);
bufw.newLine();
bufw.flush();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bufr != null){
try {
bufr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bufw != null){
try {
bufw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
4.自定义读取缓冲区的实现,模拟一个BufferedReader.
/*
* 自定义的读取缓冲区,模拟一个BufferedReader.
*
* 分析:缓冲区无非就是封装了一个数组。
* 并对外提供了更多的方法对数组进行访问。
* 其实这些方法最终操作的都是数组的角标。
*
* 缓冲的原理:
* 其实就是从源中获取一批数据装进缓冲区。
* 再从缓冲区中不断的取出一个个数据。
*
* 在此次取完后,再从源中继续取一批数据进缓冲区,
* 当源中的数据取完时,用-1作为结束标记。
*
* */
class MyBufferedReader extends Reader{
//创建一个FileReader对象,接收构造函数接收的FileReader对象。
//创建一个指针,对数组进行操作。当操作到最后一个元素后,指针应归零;
private int pos = 0;
//创建一个计数器,存储数组中元素的个数。取出一个元素就自减。当为0时就继续从硬盘中读取数据到数组。
private int count = 0;
//创建一个数组,作为缓冲区。
private char[] buf = new char[1024];
MyBufferedReader(Reader r){
this.r = r;
}
private Reader r =null;
//从硬盘中读取一个字符,存入数组,并返回其值
public int MyRead() throws IOException {
//1.从源中获取一批数据到缓冲区中。需要先做判断,只有计数器为0时,才需要从源中获取数据。
if( count == 0 ){
count = r.read(buf);//可以获取数组中存放的元素个数
pos = 0;//每次获取数据到缓冲区后,角标置为0;
}
if (count<0){
return -1;
}
char ch = buf[pos];
pos++;
count--;
return ch;
}
public String MyReadLine() throws IOException {
//创建一个行缓冲区
StringBuilder sb = new StringBuilder();
int ch = 0;
while((ch = MyRead())!= -1){
//当读到'\r'读到了行结束标志,跳过这一次不把ch存入到行缓冲区。
if (ch=='\r'){
continue;
}
if (ch=='\n'){
return sb.toString();
}
//从缓冲区读到的字符,存储到缓存行数据的缓冲区。
sb.append((char) ch);
}
if (sb.length() != 0 ){
return sb.toString();
}
return null;
}
@Override
public int read(@NotNull char[] cbuf, int off, int len) throws IOException {
return 0;
}
public void close() throws IOException {
r.close();
}
}
class MyLineNumberReader extends MyBufferedReader{
private int LineNumber = 0;
MyLineNumberReader(Reader r) {
super(r);
}
public int getLineNumber() {
return LineNumber;
}
public String MyReadLine() throws IOException {
StringBuilder sb = new StringBuilder();
int ch = 0;
while((ch = MyRead())!= -1){
if (ch=='\r'){
continue;
}
if (ch=='\n'){
LineNumber++;
return sb.toString();
}
//从缓冲区读到的字符,存储到缓存行数据的缓冲区。
sb.append((char) ch);
}
if (sb.length() != 0 ){
LineNumber++;
return sb.toString();
}
return null;
}
}
5.装饰设计模式:
对一组对象的功能进行增强时,就可以使用该设计模式。
装饰和继承都可以实现一样的特点:功能的扩展增强。那么两者有什么区别呢?
下面就来举个列子:
首先有一个继承体系。
Writer
TextWriter:用于操作文本。
MediaWriter:用于操作媒体。
想要对操作的动作提高效率。按照面向对象,可以通过继承对具体的对象进行功能的扩展,效率的提高需要加入缓冲技术。
如下:
Writer
TextWriter:用于操作文本
BufferedTextWriter:加入了缓冲技术的操作文本的流对象。
MediaWriter:用于操作媒体。
BufferedMediaWriter:加入了缓冲技术的操作媒体的流对象。
这样做并不理想。
如果这个体系进行功能扩展,有多了几个流对象,那么这个流要提高效率,
是不是也要产生子类呢?是,这时就会发现只为提高功能,进行的继承,
导致继承体系越来越臃肿,不够灵活。
重新思考这个问题?
既然加入的都是同一种技术--缓冲。
前一种是让缓冲和具体的对象相结合。
可不可以将缓冲进行单独的封装,哪个对象需要缓冲就将对象和缓冲相关联。
class Buffer{
Buffer(TextWriter w){
}
Buffer(MediaWriter w){
}
class Buffer extends Writer{
Buffer(Writer w){
}
}
Writer
TextWriter:用于操作文本。
MediaWriter:用于操作媒体。
BufferWriter:用于提高效率。
装饰类比继承更为灵活。
特点:装饰类和被装饰的类必须所属同一个接口或者父类。