java io系列24之 BufferedWriter(字符缓冲输出流)

本文摘抄至 : skywang12345

摘要 : BufferedWriter、缓存字符输出流、他的功能是为传入的底层字符输出流提供缓存功能、同样当使用底层字符输出流向目的地中写入字符或者字符数组时、每写入一次就要打开一次到目的地的连接、这样频繁的访问不断效率底下、也有可能会对存储介质造成一定的破坏、比如当我们向磁盘中不断的写入字节时、夸张一点、将一个非常大单位是G的字节数据写入到磁盘的指定文件中的、没写入一个字节就要打开一次到这个磁盘的通道、这个结果无疑是恐怖的、而当我们使用BufferedWriter将底层字符输出流、比如FileReader包装一下之后、我们可以在程序中先将要写入到文件中的字符写入到BufferedWriter的内置缓存空间中、然后当达到一定数量时、一次性写入FileReader流中、此时、FileReader就可以打开一次通道、将这个数据块写入到文件中、这样做虽然不可能达到一次访问就将所有数据写入磁盘中的效果、但也大大提高了效率和减少了磁盘的访问量!这就是其意义所在、
他的具体 工作原理在这里简单提一下:当程序中每次将字符或者字符数组写入到BufferedWriter中时、都会检查BufferedWriter中的缓存字符数组buf(buf的大小是默认的或者在创建bw时指定的、一般使用默认的就好)是否存满、如果没有存满则将字符写入到buf中、如果存满、则调用底层的writer(char[] b, int off, int len)将buf中的所有字符一次性写入到底层out中、如果写入的是字符数组、如果buf中已满则同上面满的时候的处理、如果能够存下写入的字符数组、则存入buf中、如果存不下、并且要写入buf的字符个数小于buf的长度、则将buf中所有字符写入到out中、然后将要写入的字符存放到buf中(从下标0开始存放)、如果要写入out中的字符超过buf的长度、则直接写入out中、

BufferedWriter 介绍


BufferedWriter 是缓冲字符输出流。它继承于 Writer。
BufferedWriter 的作用是为其它 输出流添加一些缓冲功能

BufferedWriter 函数列表

// 构造函数
BufferedWriter(Writer out) 
BufferedWriter(Writer out, int sz) 

void    close()                              // 关闭此流,但要先刷新它。
void    flush()                              // 刷新该流的缓冲。
void    newLine()                            // 写入一个行分隔符。
void    write(char[] cbuf, int off, int len) // 写入字符数组的某一部分。
void    write(int c)                         // 写入单个字符。
void    write(String s, int off, int len)    // 写入字符串的某一部分。

BufferedWriter 源码分析(基于jdk1.7.40)


package java.io;


public class BufferedWriter extends Writer {

    //输出流对象
    private Writer out;

    //保存“缓存输出流”数据的字符数组
    private char cb[];
    //nChars 是 cb缓冲区中字符的总个数
    //nextChar 是下一个要读取的字符在 cb缓冲区的位置
    private int nChars, nextChar;

    //默认字符缓冲去大小 (8k)
    private static int defaultCharBufferSize = 8192;

    //行分隔符
    private String lineSeparator;

    //构造函数,传入“writer对象”,默认是缓冲区大小 8k
    public BufferedWriter(Writer out) {
        this(out, defaultCharBufferSize);
    }

    //构造函数,传入“Writer对象”,指定缓冲区大小是 sz
    public BufferedWriter(Writer out, int sz) {
        super(out);
        if (sz <= 0)
            throw new IllegalArgumentException("Buffer size <= 0");
        this.out = out;
        cb = new char[sz];
        nChars = sz;
        nextChar = 0;

        lineSeparator = java.security.AccessController.doPrivileged(
            new sun.security.action.GetPropertyAction("line.separator"));
    }

    // 确保“BufferedWriter”是打开状态
    private void ensureOpen() throws IOException {
        if (out == null)
            throw new IOException("Stream closed");
    }

    // 对缓冲区执行flush()操作,将缓冲区的数据写入到Writer中
    void flushBuffer() throws IOException {
        synchronized (lock) {
            ensureOpen();
            if (nextChar == 0)
                return;
            out.write(cb, 0, nextChar);
            nextChar = 0;
        }
    }

    //将 c写入到缓冲区中,先将 c转换为 char,然后将其写入缓冲区
    public void write(int c) throws IOException {
        synchronized (lock) {
            ensureOpen();
            //如实缓冲区满, 将缓冲数据写入到输出流中
            if (nextChar >= nChars)
                flushBuffer();
            cb[nextChar++] = (char) c;
        }
    }

    //返回, a,b中的较小数
    private int min(int a, int b) {
        if (a < b) return a;
        return b;
    }

    //将字符数组 cbuf写入到缓冲中,从 cbuf的off位置开始写入,写入长度为 len
    public void write(char cbuf[], int off, int len) throws IOException {
        synchronized (lock) {
            ensureOpen();
            if ((off < 0) || (off > cbuf.length) || (len < 0) ||
                ((off + len) > cbuf.length) || ((off + len) < 0)) {
                throw new IndexOutOfBoundsException();
            } else if (len == 0) {
                return;
            }

            if (len >= nChars) {
                /* If the request length exceeds the size of the output buffer,
                   flush the buffer and then write the data directly.  In this
                   way buffered streams will cascade harmlessly. */
                flushBuffer();
                out.write(cbuf, off, len);
                return;
            }

            int b = off, t = off + len;
            while (b < t) {
                int d = min(nChars - nextChar, t - b);
                System.arraycopy(cbuf, b, cb, nextChar, d);
                b += d;
                nextChar += d;
                if (nextChar >= nChars)
                    flushBuffer();
            }
        }
    }

    //将字符串 a 写入到缓冲中,从 a的off位置开始写入,写入长度为 len。
    public void write(String s, int off, int len) throws IOException {
        synchronized (lock) {
            ensureOpen();

            int b = off, t = off + len;
            while (b < t) {
                int d = min(nChars - nextChar, t - b);
                s.getChars(b, b + d, cb, nextChar);
                b += d;
                nextChar += d;
                if (nextChar >= nChars)
                    flushBuffer();
            }
        }
    }

    //将换行符写入缓冲中
    public void newLine() throws IOException {
        write(lineSeparator);
    }

    //清空缓存数据
    public void flush() throws IOException {
        synchronized (lock) {
            flushBuffer();
            out.flush();
        }
    }

    public void close() throws IOException {
        synchronized (lock) {
            if (out == null) {
                return;
            }
            try (Writer w = out) {
                flushBuffer();
            } finally {
                out = null;
                cb = null;
            }
        }
    }

}

说明:

BufferedWriter通过字符数组来缓冲数据,当缓冲区满或者用户调用flush()函数时,它就会将缓冲区的数据写入到输出流中。

示例代码


关于BufferedWriter中API的详细用法,参考示例代码(BufferedWriterTest.java):

public class BufferedWriterTest {

    // 对应英文字母“abcdefghijklmnopqrstuvwxyz”
    private static final char[] ArrayLetters = new char[] 
            {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};

    public static void main(String[] args) {

         testBufferedWriter() ;
    }

    private static void testBufferedWriter() {

        // 创建“文件输出流”对应的BufferedWriter

        try {
            File file = new File("bufferwriter.txt") ;
            BufferedWriter out = new BufferedWriter(
                    new FileWriter(file)) ;

            // 将ArrayLetters数组的前10个字符写入到输出流中
            out.write(ArrayLetters, 0, 10) ;
            // 将“换行符\n”写入到输出流中
            out.write("\n") ;

            out.flush() ;

//          readUserInput() ;
            out.close() ;

        } catch (Exception e) {
            e.printStackTrace() ;
        }
    }


    private static void readUserInput() {
        System.out.println("please input a text:");
        Scanner reader = new Scanner(System.in) ;
        // 等待一个输入
        String str = reader.next() ;
        System.out.printf("the input is : %s\n", str);

    }
}

运行结果:

生成文件“bufferwriter.txt”,文件的内容是“abcdefghij”。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值