Java
Java IO

Java IO 22 - BufferedWriter详解

简介:流是一组有顺序的,有起点和终点的字节集合。是对设备文件间数据传输的总称和抽象。

1. BufferedWriter介绍

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

2. 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) // 写入字符串的某一部分。

3. BufferedWriter源码分析

下面是BufferedWriter的源码,基于JDK 1.7.0_07:

  • package java.io;
  • public class BufferedWriter extends Writer {
  • // 输出流对象
  • private Writer out;
  • // 保存缓冲输出流数据的字符数组
  • private char cb[];
  • // nChars是cb缓冲区中字符的总的个数
  • // nextChar是下一个要读取的字符在cb缓冲区中的位置
  • private int nChars, nextChar;
  • // 默认字符缓冲区大小
  • 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();
  • }
  • }
  • }
  • // 将字符串s写入到缓冲中,从s的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 {
  • flushBuffer();
  • } finally {
  • out.close();
  • out = null;
  • cb = null;
  • }
  • }
  • }
  • }

4. BufferedWriter示例

  • package com.coderap;
  • import java.io.BufferedWriter;
  • import java.io.FileWriter;
  • import java.io.IOException;
  • public class BufferedWriterTest {
  • public static void main(String[] args) throws IOException {
  • BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("file.data"));
  • // 行号
  • int lineNumber = 0;
  • for (int i = 0; i < 26; i++) {
  • // 写入行号
  • if ("ahou".indexOf('a' + i) != -1) {
  • bufferedWriter.write((++lineNumber + ". "));
  • }
  • // 写入字符
  • bufferedWriter.write('a' + i);
  • if ("gntz".indexOf('a' + i) != -1) {
  • // 写入换行
  • bufferedWriter.write('\n');
  • } else if ("qw".indexOf('a' + i) != -1) {
  • // 写入空格
  • bufferedWriter.write(' ');
  • }
  • }
  • for (int i = 0; i < 26; i++) {
  • // 写入行号
  • if ("AHOU".indexOf('A' + i) != -1) {
  • bufferedWriter.write((++lineNumber + ". "));
  • }
  • // 写入字符
  • bufferedWriter.write('A' + i);
  • if ("GNTZ".indexOf('A' + i) != -1) {
  • // 写入换行
  • bufferedWriter.write('\n');
  • } else if ("QW".indexOf('A' + i) != -1) {
  • // 写入空格
  • bufferedWriter.write(' ');
  • }
  • }
  • bufferedWriter.close();
  • }
  • }

运行上述代码会创建一个file.data文件,该文件内容如下:

  • 1. abcdefg
  • 2. hijklmn
  • 3. opq rst
  • 4. uvw xyz
  • 5. ABCDEFG
  • 6. HIJKLMN
  • 7. OPQ RST
  • 8. UVW XYZ