ファイル等を書き込む際に,バッファリングを行って高速化するWriterクラスである。Writerクラスのインスタンスoutをラップしている。バッファはchar型の配列でディフォルトのサイズは8192と定義されている。
コンストラクタは次のようなものが定義されている。一つ目のコンストラクタは,引数を上述のディフォルトバッファサイズと共に2つ目のコンストラクタへ渡している。そして,バッファサイズはnCharsというインスタンス変数に保存される。また,次に書き込む配列インデックスを表すnextCharというインスタンス変数に0がセットされる。
- BufferedWriter(Writer out)
- BufferedWriter(Writer out, int sz)
write(int c)メソッドはこのクラスの中では低レベルのメソッドで,int型の値をバッファに書き出す。そして,次に書き込むバッファ位置がバッファサイズを超えていたら,flushBuffer()メソッドを呼び出して,バッファをフラッシュする。
flushBuffer() メソッドでは,ラップしているWriterクラスのwrite()メソッドを用いてバッファの内容を書き込み,次に書き込むバッファ位置を示すnextCharを0に戻す。
write(char cbuf[], int off, int len)メソッドはchar型の配列で渡されたデータをオフセットと長さを指定してバッファに書き込む。この時,長さがバッファサイズを超えている場合には,直接ラップしているWriterクラスのwriteメソッドを呼び出している。バッファサイズより大きいものを書き込もうとしたら,バッファの効果がなくなるので合理的な処理である。一方,バッファサイズより書き込むデータが短い場合はSystem.arraycopyメソッドを使って,データをバッファにコピーする。
public void write(String s, int off, int len)メソッドは,文字列をバッファに書き込む。StringクラスのgetChars()メソッドでchar型の配列に変換したものを書き込んでいるに過ぎない。
* Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.io;
public class BufferedWriter extends Writer {
private Writer out;
private char cb[];
private int nChars, nextChar;
private static int defaultCharBufferSize = 8192;
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;
}
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) {
/* 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(System.lineSeparator());
}
public void flush() throws IOException {
synchronized (lock) {
flushBuffer();
out.flush();
}
}
@SuppressWarnings("try")
public void close() throws IOException {
synchronized (lock) {
if (out == null) {
return;
}
try (Writer w = out) {
flushBuffer();
} finally {
out = null;
cb = null;
}
}
}
}