1 /*
2  * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package java.io;
27 
28 
29 /**
30  * Abstract class for writing to character streams.  The only methods that a
31  * subclass must implement are write(char[], int, int), flush(), and close().
32  * Most subclasses, however, will override some of the methods defined here in
33  * order to provide higher efficiency, additional functionality, or both.
34  *
35  * @see Writer
36  * @see   BufferedWriter
37  * @see   CharArrayWriter
38  * @see   FilterWriter
39  * @see   OutputStreamWriter
40  * @see     FileWriter
41  * @see   PipedWriter
42  * @see   PrintWriter
43  * @see   StringWriter
44  * @see Reader
45  *
46  * @author      Mark Reinhold
47  * @since       JDK1.1
48  */
49 
50 public abstract class Writer implements Appendable, Closeable, Flushable {
51 
52     /**
53      * Temporary buffer used to hold writes of strings and single characters
54      */
55     private char[] writeBuffer;
56 
57     /**
58      * Size of writeBuffer, must be >= 1
59      */
60     private static final int WRITE_BUFFER_SIZE = 1024;
61 
62     /**
63      * The object used to synchronize operations on this stream.  For
64      * efficiency, a character-stream object may use an object other than
65      * itself to protect critical sections.  A subclass should therefore use
66      * the object in this field rather than <tt>this</tt> or a synchronized
67      * method.
68      */
69     protected Object lock;
70 
71     /**
72      * Creates a new character-stream writer whose critical sections will
73      * synchronize on the writer itself.
74      */
Writer()75     protected Writer() {
76         this.lock = this;
77     }
78 
79     /**
80      * Creates a new character-stream writer whose critical sections will
81      * synchronize on the given object.
82      *
83      * @param  lock
84      *         Object to synchronize on
85      */
Writer(Object lock)86     protected Writer(Object lock) {
87         if (lock == null) {
88             throw new NullPointerException();
89         }
90         this.lock = lock;
91     }
92 
93     /**
94      * Writes a single character.  The character to be written is contained in
95      * the 16 low-order bits of the given integer value; the 16 high-order bits
96      * are ignored.
97      *
98      * <p> Subclasses that intend to support efficient single-character output
99      * should override this method.
100      *
101      * @param  c
102      *         int specifying a character to be written
103      *
104      * @throws  IOException
105      *          If an I/O error occurs
106      */
write(int c)107     public void write(int c) throws IOException {
108         synchronized (lock) {
109             if (writeBuffer == null){
110                 writeBuffer = new char[WRITE_BUFFER_SIZE];
111             }
112             writeBuffer[0] = (char) c;
113             write(writeBuffer, 0, 1);
114         }
115     }
116 
117     /**
118      * Writes an array of characters.
119      *
120      * @param  cbuf
121      *         Array of characters to be written
122      *
123      * @throws  IOException
124      *          If an I/O error occurs
125      */
write(char cbuf[])126     public void write(char cbuf[]) throws IOException {
127         write(cbuf, 0, cbuf.length);
128     }
129 
130     /**
131      * Writes a portion of an array of characters.
132      *
133      * @param  cbuf
134      *         Array of characters
135      *
136      * @param  off
137      *         Offset from which to start writing characters
138      *
139      * @param  len
140      *         Number of characters to write
141      *
142      * @throws  IOException
143      *          If an I/O error occurs
144      */
write(char cbuf[], int off, int len)145     abstract public void write(char cbuf[], int off, int len) throws IOException;
146 
147     /**
148      * Writes a string.
149      *
150      * @param  str
151      *         String to be written
152      *
153      * @throws  IOException
154      *          If an I/O error occurs
155      */
write(String str)156     public void write(String str) throws IOException {
157         write(str, 0, str.length());
158     }
159 
160     /**
161      * Writes a portion of a string.
162      *
163      * @param  str
164      *         A String
165      *
166      * @param  off
167      *         Offset from which to start writing characters
168      *
169      * @param  len
170      *         Number of characters to write
171      *
172      * @throws  IndexOutOfBoundsException
173      *          If <tt>off</tt> is negative, or <tt>len</tt> is negative,
174      *          or <tt>off+len</tt> is negative or greater than the length
175      *          of the given string
176      *
177      * @throws  IOException
178      *          If an I/O error occurs
179      */
write(String str, int off, int len)180     public void write(String str, int off, int len) throws IOException {
181         synchronized (lock) {
182             char cbuf[];
183             if (len <= WRITE_BUFFER_SIZE) {
184                 if (writeBuffer == null) {
185                     writeBuffer = new char[WRITE_BUFFER_SIZE];
186                 }
187                 cbuf = writeBuffer;
188             } else {    // Don't permanently allocate very large buffers.
189                 cbuf = new char[len];
190             }
191             str.getChars(off, (off + len), cbuf, 0);
192             write(cbuf, 0, len);
193         }
194     }
195 
196     /**
197      * Appends the specified character sequence to this writer.
198      *
199      * <p> An invocation of this method of the form <tt>out.append(csq)</tt>
200      * behaves in exactly the same way as the invocation
201      *
202      * <pre>
203      *     out.write(csq.toString()) </pre>
204      *
205      * <p> Depending on the specification of <tt>toString</tt> for the
206      * character sequence <tt>csq</tt>, the entire sequence may not be
207      * appended. For instance, invoking the <tt>toString</tt> method of a
208      * character buffer will return a subsequence whose content depends upon
209      * the buffer's position and limit.
210      *
211      * @param  csq
212      *         The character sequence to append.  If <tt>csq</tt> is
213      *         <tt>null</tt>, then the four characters <tt>"null"</tt> are
214      *         appended to this writer.
215      *
216      * @return  This writer
217      *
218      * @throws  IOException
219      *          If an I/O error occurs
220      *
221      * @since  1.5
222      */
append(CharSequence csq)223     public Writer append(CharSequence csq) throws IOException {
224         if (csq == null)
225             write("null");
226         else
227             write(csq.toString());
228         return this;
229     }
230 
231     /**
232      * Appends a subsequence of the specified character sequence to this writer.
233      * <tt>Appendable</tt>.
234      *
235      * <p> An invocation of this method of the form <tt>out.append(csq, start,
236      * end)</tt> when <tt>csq</tt> is not <tt>null</tt> behaves in exactly the
237      * same way as the invocation
238      *
239      * <pre>
240      *     out.write(csq.subSequence(start, end).toString()) </pre>
241      *
242      * @param  csq
243      *         The character sequence from which a subsequence will be
244      *         appended.  If <tt>csq</tt> is <tt>null</tt>, then characters
245      *         will be appended as if <tt>csq</tt> contained the four
246      *         characters <tt>"null"</tt>.
247      *
248      * @param  start
249      *         The index of the first character in the subsequence
250      *
251      * @param  end
252      *         The index of the character following the last character in the
253      *         subsequence
254      *
255      * @return  This writer
256      *
257      * @throws  IndexOutOfBoundsException
258      *          If <tt>start</tt> or <tt>end</tt> are negative, <tt>start</tt>
259      *          is greater than <tt>end</tt>, or <tt>end</tt> is greater than
260      *          <tt>csq.length()</tt>
261      *
262      * @throws  IOException
263      *          If an I/O error occurs
264      *
265      * @since  1.5
266      */
append(CharSequence csq, int start, int end)267     public Writer append(CharSequence csq, int start, int end) throws IOException {
268         CharSequence cs = (csq == null ? "null" : csq);
269         write(cs.subSequence(start, end).toString());
270         return this;
271     }
272 
273     /**
274      * Appends the specified character to this writer.
275      *
276      * <p> An invocation of this method of the form <tt>out.append(c)</tt>
277      * behaves in exactly the same way as the invocation
278      *
279      * <pre>
280      *     out.write(c) </pre>
281      *
282      * @param  c
283      *         The 16-bit character to append
284      *
285      * @return  This writer
286      *
287      * @throws  IOException
288      *          If an I/O error occurs
289      *
290      * @since 1.5
291      */
append(char c)292     public Writer append(char c) throws IOException {
293         write(c);
294         return this;
295     }
296 
297     /**
298      * Flushes the stream.  If the stream has saved any characters from the
299      * various write() methods in a buffer, write them immediately to their
300      * intended destination.  Then, if that destination is another character or
301      * byte stream, flush it.  Thus one flush() invocation will flush all the
302      * buffers in a chain of Writers and OutputStreams.
303      *
304      * <p> If the intended destination of this stream is an abstraction provided
305      * by the underlying operating system, for example a file, then flushing the
306      * stream guarantees only that bytes previously written to the stream are
307      * passed to the operating system for writing; it does not guarantee that
308      * they are actually written to a physical device such as a disk drive.
309      *
310      * @throws  IOException
311      *          If an I/O error occurs
312      */
flush()313     abstract public void flush() throws IOException;
314 
315     /**
316      * Closes the stream, flushing it first. Once the stream has been closed,
317      * further write() or flush() invocations will cause an IOException to be
318      * thrown. Closing a previously closed stream has no effect.
319      *
320      * @throws  IOException
321      *          If an I/O error occurs
322      */
close()323     abstract public void close() throws IOException;
324 
325 }
326