Path: blob/master/src/java.base/share/classes/java/io/BufferedWriter.java
41152 views
/*1* Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package java.io;262728/**29* Writes text to a character-output stream, buffering characters so as to30* provide for the efficient writing of single characters, arrays, and strings.31*32* <p> The buffer size may be specified, or the default size may be accepted.33* The default is large enough for most purposes.34*35* <p> A newLine() method is provided, which uses the platform's own notion of36* line separator as defined by the system property {@code line.separator}.37* Not all platforms use the newline character ('\n') to terminate lines.38* Calling this method to terminate each output line is therefore preferred to39* writing a newline character directly.40*41* <p> In general, a Writer sends its output immediately to the underlying42* character or byte stream. Unless prompt output is required, it is advisable43* to wrap a BufferedWriter around any Writer whose write() operations may be44* costly, such as FileWriters and OutputStreamWriters. For example,45*46* <pre>47* PrintWriter out48* = new PrintWriter(new BufferedWriter(new FileWriter("foo.out")));49* </pre>50*51* will buffer the PrintWriter's output to the file. Without buffering, each52* invocation of a print() method would cause characters to be converted into53* bytes that would then be written immediately to the file, which can be very54* inefficient.55*56* @see PrintWriter57* @see FileWriter58* @see OutputStreamWriter59* @see java.nio.file.Files#newBufferedWriter60*61* @author Mark Reinhold62* @since 1.163*/6465public class BufferedWriter extends Writer {6667private Writer out;6869private char cb[];70private int nChars, nextChar;7172private static int defaultCharBufferSize = 8192;7374/**75* Creates a buffered character-output stream that uses a default-sized76* output buffer.77*78* @param out A Writer79*/80public BufferedWriter(Writer out) {81this(out, defaultCharBufferSize);82}8384/**85* Creates a new buffered character-output stream that uses an output86* buffer of the given size.87*88* @param out A Writer89* @param sz Output-buffer size, a positive integer90*91* @throws IllegalArgumentException If {@code sz <= 0}92*/93public BufferedWriter(Writer out, int sz) {94super(out);95if (sz <= 0)96throw new IllegalArgumentException("Buffer size <= 0");97this.out = out;98cb = new char[sz];99nChars = sz;100nextChar = 0;101}102103/** Checks to make sure that the stream has not been closed */104private void ensureOpen() throws IOException {105if (out == null)106throw new IOException("Stream closed");107}108109/**110* Flushes the output buffer to the underlying character stream, without111* flushing the stream itself. This method is non-private only so that it112* may be invoked by PrintStream.113*/114void flushBuffer() throws IOException {115synchronized (lock) {116ensureOpen();117if (nextChar == 0)118return;119out.write(cb, 0, nextChar);120nextChar = 0;121}122}123124/**125* Writes a single character.126*127* @throws IOException If an I/O error occurs128*/129public void write(int c) throws IOException {130synchronized (lock) {131ensureOpen();132if (nextChar >= nChars)133flushBuffer();134cb[nextChar++] = (char) c;135}136}137138/**139* Our own little min method, to avoid loading java.lang.Math if we've run140* out of file descriptors and we're trying to print a stack trace.141*/142private int min(int a, int b) {143if (a < b) return a;144return b;145}146147/**148* Writes a portion of an array of characters.149*150* <p> Ordinarily this method stores characters from the given array into151* this stream's buffer, flushing the buffer to the underlying stream as152* needed. If the requested length is at least as large as the buffer,153* however, then this method will flush the buffer and write the characters154* directly to the underlying stream. Thus redundant155* {@code BufferedWriter}s will not copy data unnecessarily.156*157* @param cbuf A character array158* @param off Offset from which to start reading characters159* @param len Number of characters to write160*161* @throws IndexOutOfBoundsException162* If {@code off} is negative, or {@code len} is negative,163* or {@code off + len} is negative or greater than the length164* of the given array165*166* @throws IOException If an I/O error occurs167*/168public void write(char cbuf[], int off, int len) throws IOException {169synchronized (lock) {170ensureOpen();171if ((off < 0) || (off > cbuf.length) || (len < 0) ||172((off + len) > cbuf.length) || ((off + len) < 0)) {173throw new IndexOutOfBoundsException();174} else if (len == 0) {175return;176}177178if (len >= nChars) {179/* If the request length exceeds the size of the output buffer,180flush the buffer and then write the data directly. In this181way buffered streams will cascade harmlessly. */182flushBuffer();183out.write(cbuf, off, len);184return;185}186187int b = off, t = off + len;188while (b < t) {189int d = min(nChars - nextChar, t - b);190System.arraycopy(cbuf, b, cb, nextChar, d);191b += d;192nextChar += d;193if (nextChar >= nChars)194flushBuffer();195}196}197}198199/**200* Writes a portion of a String.201*202* @implSpec203* While the specification of this method in the204* {@linkplain java.io.Writer#write(java.lang.String,int,int) superclass}205* recommends that an {@link IndexOutOfBoundsException} be thrown206* if {@code len} is negative or {@code off + len} is negative,207* the implementation in this class does not throw such an exception in208* these cases but instead simply writes no characters.209*210* @param s String to be written211* @param off Offset from which to start reading characters212* @param len Number of characters to be written213*214* @throws IndexOutOfBoundsException215* If {@code off} is negative,216* or {@code off + len} is greater than the length217* of the given string218*219* @throws IOException If an I/O error occurs220*/221public void write(String s, int off, int len) throws IOException {222synchronized (lock) {223ensureOpen();224225int b = off, t = off + len;226while (b < t) {227int d = min(nChars - nextChar, t - b);228s.getChars(b, b + d, cb, nextChar);229b += d;230nextChar += d;231if (nextChar >= nChars)232flushBuffer();233}234}235}236237/**238* Writes a line separator. The line separator string is defined by the239* system property {@code line.separator}, and is not necessarily a single240* newline ('\n') character.241*242* @throws IOException If an I/O error occurs243*/244public void newLine() throws IOException {245write(System.lineSeparator());246}247248/**249* Flushes the stream.250*251* @throws IOException If an I/O error occurs252*/253public void flush() throws IOException {254synchronized (lock) {255flushBuffer();256out.flush();257}258}259260@SuppressWarnings("try")261public void close() throws IOException {262synchronized (lock) {263if (out == null) {264return;265}266try (Writer w = out) {267flushBuffer();268} finally {269out = null;270cb = null;271}272}273}274}275276277