View Javadoc
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       */
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       */
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      */
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      */
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      */
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      */
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      */
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      */
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      */
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      */
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      */
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      */
323     abstract public void close() throws IOException;
324 
325 }