您的位置:首页 > Web前端

Java 日看一类(5)之IO包中的BufferedWriter类

2018-02-14 11:36 309 查看
引入包和继承关系:
无引入包
继承自Writer类(类似于BufferReader)

代码注释:/**
* Writes text to a character-output stream, buffering characters so as to
* provide for the efficient writing of single characters, arrays, and strings.
*
* <p> The buffer size may be specified, or the default size may be accepted.
* The default is large enough for most purposes.
*
* <p> A newLine() method is provided, which uses the platform's own notion of
* line separator as defined by the system property <tt>line.separator</tt>.
* Not all platforms use the newline character ('\n') to terminate lines.
* Calling this method to terminate each output line is therefore preferred to
* writing a newline character directly.
*
* <p> In general, a Writer sends its output immediately to the underlying
* character or byte stream. Unless prompt output is required, it is advisable
* to wrap a BufferedWriter around any Writer whose write() operations may be
* costly, such as FileWriters and OutputStreamWriters. For example,
*
* <pre>
* PrintWriter out
* = new PrintWriter(new BufferedWriter(new FileWriter("foo.out")));
* </pre>
*
* will buffer the PrintWriter's output to the file. Without buffering, each
* invocation of a print() method would cause characters to be converted into
* bytes that would then be written immediately to the file, which can be very
* inefficient.
*
* @see PrintWriter
* @see FileWriter
* @see OutputStreamWriter
* @see java.nio.file.Files#newBufferedWriter
*
* @author Mark Reinhold
* @since JDK1.1
*/大意如下:
向字符输出流写入文本时,对字符进行缓冲处理是一种高效的处理方式,尤其是逐个的字符写入,数组结构写入或者字符串结构写入
缓冲区的大小可被设定,默认大小足以满足一般情况的需求
提供了newLine()方法,提供了基于不同平台的行分割方法,因为不是所有平台都是用'\n'作为换行符,所以使用newLine方法是首选。
一般情况下,Writer类总是立即将数据输出到底层的字符流或比特流中。除非程序需要即刻输出,否则使用BufferedWriter封装时最好的选择。(对于write()方法开销较大的Writer类十分必要)
例如: PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("foo.out")));对PrintWriter类进行了缓冲。如果没有缓冲,任意一个对print方法的调用将会使字符转化为byte并且立刻写入到文件中,这是非常低效率的。

BufferedWriter含有五个成员变量:
被其封装的Writer类:private Writer out;缓冲区:private char cb[];缓冲区最大长度(这个和前几个不一样)和当前读取位置指针:private int nChars, nextChar;默认缓冲区长度:private static int defaultCharBufferSize = 8192;行分割符字符串
private String lineSeparator;

含有十一个方法:
构造函数:(默认大小缓冲区)public BufferedWriter(Writer out) {
this(out, defaultCharBufferSize);
}构造函数:(自定义大小)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"));//该类实现一个接口,对传入的字符串调用System.getProperty(),获取当前系统行分割符(line.separator为该方法的保留限定字)
}检测输出流状态:private void ensureOpen() throws IOException {
if (out == null)
throw new IOException("Stream closed");
}清空缓冲区(将缓冲区内容全部写入输出流):
void flushBuffer() throws IOException {
synchronized (lock) {
ensureOpen();
if (nextChar == 0)
return;
out.write(cb, 0, nextChar);
nextChar = 0;
}
}向缓冲区中写入字符:
public void write(int c) throws IOException {
synchronized (lock) {
ensureOpen();
if (nextChar >= nChars)//缓冲区满了就清空缓冲区
flushBuffer();
cb[nextChar++] = (char) c;
}
}
两数求最小值:(我也不知道源码里为啥有个这……和前面几个风格完全不搭)private int min(int a, int b) {
if (a < b) return a;
return b;
}向缓冲区中写入数组: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) {//写入长度大于缓冲区长度(前几个里面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();
}
}
}写入字符串: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;
}
}
}

和前几个做的Buffered类的代码命名习惯有显著差别,不过整体思路没有大变化
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: