001: /*
002: * Copyright 1996-2005 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package java.io;
027:
028: /**
029: * Abstract class for writing to character streams. The only methods that a
030: * subclass must implement are write(char[], int, int), flush(), and close().
031: * Most subclasses, however, will override some of the methods defined here in
032: * order to provide higher efficiency, additional functionality, or both.
033: *
034: * @see Writer
035: * @see BufferedWriter
036: * @see CharArrayWriter
037: * @see FilterWriter
038: * @see OutputStreamWriter
039: * @see FileWriter
040: * @see PipedWriter
041: * @see PrintWriter
042: * @see StringWriter
043: * @see Reader
044: *
045: * @version 1.35, 07/05/05
046: * @author Mark Reinhold
047: * @since JDK1.1
048: */
049:
050: public abstract class Writer implements Appendable, Closeable,
051: Flushable {
052:
053: /**
054: * Temporary buffer used to hold writes of strings and single characters
055: */
056: private char[] writeBuffer;
057:
058: /**
059: * Size of writeBuffer, must be >= 1
060: */
061: private final int writeBufferSize = 1024;
062:
063: /**
064: * The object used to synchronize operations on this stream. For
065: * efficiency, a character-stream object may use an object other than
066: * itself to protect critical sections. A subclass should therefore use
067: * the object in this field rather than <tt>this</tt> or a synchronized
068: * method.
069: */
070: protected Object lock;
071:
072: /**
073: * Creates a new character-stream writer whose critical sections will
074: * synchronize on the writer itself.
075: */
076: protected Writer() {
077: this .lock = this ;
078: }
079:
080: /**
081: * Creates a new character-stream writer whose critical sections will
082: * synchronize on the given object.
083: *
084: * @param lock
085: * Object to synchronize on
086: */
087: protected Writer(Object lock) {
088: if (lock == null) {
089: throw new NullPointerException();
090: }
091: this .lock = lock;
092: }
093:
094: /**
095: * Writes a single character. The character to be written is contained in
096: * the 16 low-order bits of the given integer value; the 16 high-order bits
097: * are ignored.
098: *
099: * <p> Subclasses that intend to support efficient single-character output
100: * should override this method.
101: *
102: * @param c
103: * int specifying a character to be written
104: *
105: * @throws IOException
106: * If an I/O error occurs
107: */
108: public void write(int c) throws IOException {
109: synchronized (lock) {
110: if (writeBuffer == null) {
111: writeBuffer = new char[writeBufferSize];
112: }
113: writeBuffer[0] = (char) c;
114: write(writeBuffer, 0, 1);
115: }
116: }
117:
118: /**
119: * Writes an array of characters.
120: *
121: * @param cbuf
122: * Array of characters to be written
123: *
124: * @throws IOException
125: * If an I/O error occurs
126: */
127: public void write(char cbuf[]) throws IOException {
128: write(cbuf, 0, cbuf.length);
129: }
130:
131: /**
132: * Writes a portion of an array of characters.
133: *
134: * @param cbuf
135: * Array of characters
136: *
137: * @param off
138: * Offset from which to start writing characters
139: *
140: * @param len
141: * Number of characters to write
142: *
143: * @throws IOException
144: * If an I/O error occurs
145: */
146: abstract public void write(char cbuf[], int off, int len)
147: throws IOException;
148:
149: /**
150: * Writes a string.
151: *
152: * @param str
153: * String to be written
154: *
155: * @throws IOException
156: * If an I/O error occurs
157: */
158: public void write(String str) throws IOException {
159: write(str, 0, str.length());
160: }
161:
162: /**
163: * Writes a portion of a string.
164: *
165: * @param str
166: * A String
167: *
168: * @param off
169: * Offset from which to start writing characters
170: *
171: * @param len
172: * Number of characters to write
173: *
174: * @throws IndexOutOfBoundsException
175: * If <tt>off</tt> is negative, or <tt>len</tt> is negative,
176: * or <tt>off+len</tt> is negative or greater than the length
177: * of the given string
178: *
179: * @throws IOException
180: * If an I/O error occurs
181: */
182: public void write(String str, int off, int len) throws IOException {
183: synchronized (lock) {
184: char cbuf[];
185: if (len <= writeBufferSize) {
186: if (writeBuffer == null) {
187: writeBuffer = new char[writeBufferSize];
188: }
189: cbuf = writeBuffer;
190: } else { // Don't permanently allocate very large buffers.
191: cbuf = new char[len];
192: }
193: str.getChars(off, (off + len), cbuf, 0);
194: write(cbuf, 0, len);
195: }
196: }
197:
198: /**
199: * Appends the specified character sequence to this writer.
200: *
201: * <p> An invocation of this method of the form <tt>out.append(csq)</tt>
202: * behaves in exactly the same way as the invocation
203: *
204: * <pre>
205: * out.write(csq.toString()) </pre>
206: *
207: * <p> Depending on the specification of <tt>toString</tt> for the
208: * character sequence <tt>csq</tt>, the entire sequence may not be
209: * appended. For instance, invoking the <tt>toString</tt> method of a
210: * character buffer will return a subsequence whose content depends upon
211: * the buffer's position and limit.
212: *
213: * @param csq
214: * The character sequence to append. If <tt>csq</tt> is
215: * <tt>null</tt>, then the four characters <tt>"null"</tt> are
216: * appended to this writer.
217: *
218: * @return This writer
219: *
220: * @throws IOException
221: * If an I/O error occurs
222: *
223: * @since 1.5
224: */
225: public Writer append(CharSequence csq) throws IOException {
226: if (csq == null)
227: write("null");
228: else
229: write(csq.toString());
230: return this ;
231: }
232:
233: /**
234: * Appends a subsequence of the specified character sequence to this writer.
235: * <tt>Appendable</tt>.
236: *
237: * <p> An invocation of this method of the form <tt>out.append(csq, start,
238: * end)</tt> when <tt>csq</tt> is not <tt>null</tt> behaves in exactly the
239: * same way as the invocation
240: *
241: * <pre>
242: * out.write(csq.subSequence(start, end).toString()) </pre>
243: *
244: * @param csq
245: * The character sequence from which a subsequence will be
246: * appended. If <tt>csq</tt> is <tt>null</tt>, then characters
247: * will be appended as if <tt>csq</tt> contained the four
248: * characters <tt>"null"</tt>.
249: *
250: * @param start
251: * The index of the first character in the subsequence
252: *
253: * @param end
254: * The index of the character following the last character in the
255: * subsequence
256: *
257: * @return This writer
258: *
259: * @throws IndexOutOfBoundsException
260: * If <tt>start</tt> or <tt>end</tt> are negative, <tt>start</tt>
261: * is greater than <tt>end</tt>, or <tt>end</tt> is greater than
262: * <tt>csq.length()</tt>
263: *
264: * @throws IOException
265: * If an I/O error occurs
266: *
267: * @since 1.5
268: */
269: public Writer append(CharSequence csq, int start, int end)
270: throws IOException {
271: CharSequence cs = (csq == null ? "null" : csq);
272: write(cs.subSequence(start, end).toString());
273: return this ;
274: }
275:
276: /**
277: * Appends the specified character to this writer.
278: *
279: * <p> An invocation of this method of the form <tt>out.append(c)</tt>
280: * behaves in exactly the same way as the invocation
281: *
282: * <pre>
283: * out.write(c) </pre>
284: *
285: * @param c
286: * The 16-bit character to append
287: *
288: * @return This writer
289: *
290: * @throws IOException
291: * If an I/O error occurs
292: *
293: * @since 1.5
294: */
295: public Writer append(char c) throws IOException {
296: write(c);
297: return this ;
298: }
299:
300: /**
301: * Flushes the stream. If the stream has saved any characters from the
302: * various write() methods in a buffer, write them immediately to their
303: * intended destination. Then, if that destination is another character or
304: * byte stream, flush it. Thus one flush() invocation will flush all the
305: * buffers in a chain of Writers and OutputStreams.
306: *
307: * <p> If the intended destination of this stream is an abstraction provided
308: * by the underlying operating system, for example a file, then flushing the
309: * stream guarantees only that bytes previously written to the stream are
310: * passed to the operating system for writing; it does not guarantee that
311: * they are actually written to a physical device such as a disk drive.
312: *
313: * @throws IOException
314: * If an I/O error occurs
315: */
316: abstract public void flush() throws IOException;
317:
318: /**
319: * Closes the stream, flushing it first. Once the stream has been closed,
320: * further write() or flush() invocations will cause an IOException to be
321: * thrown. Closing a previously closed stream has no effect.
322: *
323: * @throws IOException
324: * If an I/O error occurs
325: */
326: abstract public void close() throws IOException;
327:
328: }
|