Java IO 之 BufferedWriter 字符输出缓冲类使用示例和详解

版权声明:觉得此文有用的,不嫌麻烦的,就留个言呐,或者点个赞呐(额,就是文章底部的“顶”啦),要是嫌弃麻烦呢,也麻烦点个赞嘛,要是实在不想点赞呢,也不是不可以。 但是,你要是想踩一脚呢,那还是赶紧,马上,快快的闪人。 小心我手里三十米长的大刀。 哼哼。想想都怕 !!! https://blog.csdn.net/qq_27093465/article/details/53308032

BufferedWriter:
将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
可以指定缓冲区的大小,或者接受默认的大小。在大多数情况下,默认值就足够大了。

通常 Writer(即不使用缓存的文件IO输出流)将其输出立即发送到底层字符或字节流。
除非要求及时输出,否则建议用 BufferedWriter 包装所有 write() 操作可能开销很高的 Writer(如 FileWriters 和 OutputStreamWriters)。例如, 
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("out.txt")));
将缓冲 PrintWriter 对文件的输出。如果没有缓冲,则每次调用 print() 方法会导致将字符转换为字节,然后立即写入到文件,而这是极其低效的。
有点绕,意思就是在往外写文件的时候,若是没有硬性要求,那就使用缓存,来提高写的效率。文件底层存储的时候,是二进制数,也算是字节流吧。


该类提供了 newLine() 方法,它使用平台自己的行分隔符概念,此概念由系统属性 line.separator 定义。并非所有平台都使用新行符 ('\n') 来终止各行。因此调用此方法来终止每个输出行要优于直接写入新行符。


缓冲技术的最终原理
就是这个BufferedWriter对象里面封装了一个数组,先把数据都给存起来,存完了,再一次性的写出去。这就不用我们自己定义数组,用起来很方便。
只要将需要被提高效率的流对象作为参数传递给缓冲区的构造函数即可,如下:
FileWriter fw = new FileWriter("buf.txt");//打算向buf.txt文件里面写数据
BufferedWriter bufw = new BufferedWriter(fw);


write():看下面结构图,在BufferedWriter类里面override了几个write方法,还有几个可以直接使用父类Writer的write方法。
flush():只要用到缓冲区,就要记得刷新,刷新时机自由。override父类方法
close():其实看似是关闭缓冲区,但是缓冲区是没有关闭的概念的,缓冲区是内存中的一个数组而已,非系统资源。这个是override父类的方法,实际是关闭写流,即new BufferedWriter传入的流资源的关闭。关闭的时候,会刷新一次。
newLine():该缓冲区中提供了一个跨平台的换行符。例如Windows的换行是"\r\n",Linux的则是"\n",可以自动确定。


简单测试代码:

package com.lxk.FileTest;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

class BufferedWriterDemo {
    public static void main(String[] args) {
        BufferedWriter bufw = null;
        try {
            //创建一个字符写入流对象。
            FileWriter fw = new FileWriter("buf.txt");
            //为了提高字符写入流效率。加入了缓冲技术。
            //只要将需要被提高效率的流对象作为参数传递给缓冲区的构造函数即可。
            bufw = new BufferedWriter(fw);
            for (int x = 1; x < 5; x++) {
                bufw.write("abcd" + x);
                bufw.newLine();
                bufw.flush();
            }
        } catch (IOException e) {
            System.out.println(e.getMessage());
        } finally {
            //关闭缓冲区,缓冲区关闭其实就是其中的流对象的关闭,所以流资源已经不需要关闭啦。
            if (bufw != null) {
                try {
                    bufw.close();
                } catch (IOException e) {
                    System.out.println(e.getMessage());
                }
            }
        }
    }
}


注意:上面演示了如何使用这个缓冲类,然后还演示了如何正确的关闭文件流。和处理异常,异常要处理的,我这只是打印出来啦,实际开发应该打印log哦。

上述代码中for循环,每次都刷缓冲一次,道理同所有的鸡蛋不能放在一个篮子里一样。即,你一直写,打算最后再一次写到文件,但是忽然异常了,啪,程序结束,搞了半天,文件一点没写。就是这么个道理。

测试结果:

就是新生成个buf.txt文件,然后有四行abcd。就不上测试图了。


以下对BufferedWriter源码的几个特殊方法做简单概述和了解。

BufferedWriter的构造函数有2个

    BufferedWriter(Writer out)          //创建一个输出缓冲区的新缓冲字符输出流。使用默认大小
    BufferedWriter(Writer out, int sz)  //创建一个使用给定大小输出缓冲区的新缓冲字符输出流。

BufferedWriter有几个属性。

    private Writer out;             //输出流,new对象的时候初始化,这也是为什么这个对象没有无参构造函数的原因。此属性必须赋值。
    private char cb[];              //缓冲区的缓冲字节数组
    private int nChars, nextChar;   //缓冲区一共的大小和下一次读的字符的下标
    private static int defaultCharBufferSize = 8192;    //缓冲区默认大小,即数组默认大小。
    private String lineSeparator;//系统的换行到底是"\n"还是"\r\n"

简单看看构造方法,基本就可以了解个大概了这个类

    public BufferedWriter(Writer out) {
        this(out, defaultCharBufferSize);//调用下面的2个参数的构造函数。
    }

    public BufferedWriter(Writer out, int sz) {
        super(out);//调用父类Writer的构造方法,Creates a new character-stream writer whose critical sections will synchronize on the given object.
        if (sz <= 0)
            throw new IllegalArgumentException("Buffer size <= 0");
        this.out = out;		//把要输出的流赋值给BufferedWriter内部的流
        cb = new char[sz];	//新建缓冲数组
        nChars = sz;		//缓冲数组的长度
        nextChar = 0;		//刚刚从头开始
        //这个就是系统权限相关的东西,就不管了。获得系统的换行到底是"\n"还是"\r\n".解释上面的所谓的跨平台换行符的意思。
        lineSeparator = java.security.AccessController.doPrivileged(
            new sun.security.action.GetPropertyAction("line.separator"));
    }

最后看这个类的整个继承关系图:








阅读更多

没有更多推荐了,返回首页