1 /* 2 * Copyright (c) 1996, 2016, 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 BufferedWriter 36 * @see CharArrayWriter 37 * @see FilterWriter 38 * @see OutputStreamWriter 39 * @see FileWriter 40 * @see PipedWriter 41 * @see PrintWriter 42 * @see StringWriter 43 * @see Reader 44 * 45 * @author Mark Reinhold 46 * @since 1.1 47 */ 48 49 public abstract class Writer implements Appendable, Closeable, Flushable { 50 51 /** 52 * Temporary buffer used to hold writes of strings and single characters 53 */ 54 private char[] writeBuffer; 55 56 /** 57 * Size of writeBuffer, must be >= 1 58 */ 59 private static final int WRITE_BUFFER_SIZE = 1024; 60 61 /** 62 * The object used to synchronize operations on this stream. For 63 * efficiency, a character-stream object may use an object other than 64 * itself to protect critical sections. A subclass should therefore use 65 * the object in this field rather than {@code this} or a synchronized 66 * method. 67 */ 68 protected Object lock; 69 70 /** 71 * Creates a new character-stream writer whose critical sections will 72 * synchronize on the writer itself. 73 */ 74 protected Writer() { 75 this.lock = this; 76 } 77 78 /** 79 * Creates a new character-stream writer whose critical sections will 80 * synchronize on the given object. 81 * 82 * @param lock 83 * Object to synchronize on 84 */ 85 protected Writer(Object lock) { 86 if (lock == null) { 87 throw new NullPointerException(); 88 } 89 this.lock = lock; 90 } 91 92 /** 93 * Writes a single character. The character to be written is contained in 94 * the 16 low-order bits of the given integer value; the 16 high-order bits 95 * are ignored. 96 * 97 * <p> Subclasses that intend to support efficient single-character output 98 * should override this method. 99 * 100 * @param c 101 * int specifying a character to be written 102 * 103 * @throws IOException 104 * If an I/O error occurs 105 */ 106 public void write(int c) throws IOException { 107 synchronized (lock) { 108 if (writeBuffer == null){ 109 writeBuffer = new char[WRITE_BUFFER_SIZE]; 110 } 111 writeBuffer[0] = (char) c; 112 write(writeBuffer, 0, 1); 113 } 114 } 115 116 /** 117 * Writes an array of characters. 118 * 119 * @param cbuf 120 * Array of characters to be written 121 * 122 * @throws IOException 123 * If an I/O error occurs 124 */ 125 public void write(char cbuf[]) throws IOException { 126 write(cbuf, 0, cbuf.length); 127 } 128 129 /** 130 * Writes a portion of an array of characters. 131 * 132 * @param cbuf 133 * Array of characters 134 * 135 * @param off 136 * Offset from which to start writing characters 137 * 138 * @param len 139 * Number of characters to write 140 * 141 * @throws IndexOutOfBoundsException 142 * Implementations should throw this exception 143 * if {@code off} is negative, or {@code len} is negative, 144 * or {@code off + len} is negative or greater than the length 145 * of the given array 146 * 147 * @throws IOException 148 * If an I/O error occurs 149 */ 150 public abstract void write(char cbuf[], int off, int len) throws IOException; 151 152 /** 153 * Writes a string. 154 * 155 * @param str 156 * String to be written 157 * 158 * @throws IOException 159 * If an I/O error occurs 160 */ 161 public void write(String str) throws IOException { 162 write(str, 0, str.length()); 163 } 164 165 /** 166 * Writes a portion of a string. 167 * 168 * @implSpec 169 * The implementation in this class throws an 170 * {@code IndexOutOfBoundsException} for the indicated conditions; 171 * overriding methods may choose to do otherwise. 172 * 173 * @param str 174 * A String 175 * 176 * @param off 177 * Offset from which to start writing characters 178 * 179 * @param len 180 * Number of characters to write 181 * 182 * @throws IndexOutOfBoundsException 183 * Implementations should throw this exception 184 * if {@code off} is negative, or {@code len} is negative, 185 * or {@code off + len} is negative or greater than the length 186 * of the given string 187 * 188 * @throws IOException 189 * If an I/O error occurs 190 */ 191 public void write(String str, int off, int len) throws IOException { 192 synchronized (lock) { 193 char cbuf[]; 194 if (len <= WRITE_BUFFER_SIZE) { 195 if (writeBuffer == null) { 196 writeBuffer = new char[WRITE_BUFFER_SIZE]; 197 } 198 cbuf = writeBuffer; 199 } else { // Don't permanently allocate very large buffers. 200 cbuf = new char[len]; 201 } 202 str.getChars(off, (off + len), cbuf, 0); 203 write(cbuf, 0, len); 204 } 205 } 206 207 /** 208 * Appends the specified character sequence to this writer. 209 * 210 * <p> An invocation of this method of the form {@code out.append(csq)} 211 * behaves in exactly the same way as the invocation 212 * 213 * <pre> 214 * out.write(csq.toString()) </pre> 215 * 216 * <p> Depending on the specification of {@code toString} for the 217 * character sequence {@code csq}, the entire sequence may not be 218 * appended. For instance, invoking the {@code toString} method of a 219 * character buffer will return a subsequence whose content depends upon 220 * the buffer's position and limit. 221 * 222 * @param csq 223 * The character sequence to append. If {@code csq} is 224 * {@code null}, then the four characters {@code "null"} are 225 * appended to this writer. 226 * 227 * @return This writer 228 * 229 * @throws IOException 230 * If an I/O error occurs 231 * 232 * @since 1.5 233 */ 234 public Writer append(CharSequence csq) throws IOException { 235 write(String.valueOf(csq)); 236 return this; 237 } 238 239 /** 240 * Appends a subsequence of the specified character sequence to this writer. 241 * {@code Appendable}. 242 * 243 * <p> An invocation of this method of the form 244 * {@code out.append(csq, start, end)} when {@code csq} 245 * is not {@code null} behaves in exactly the 246 * same way as the invocation 247 * 248 * <pre>{@code 249 * out.write(csq.subSequence(start, end).toString()) 250 * }</pre> 251 * 252 * @param csq 253 * The character sequence from which a subsequence will be 254 * appended. If {@code csq} is {@code null}, then characters 255 * will be appended as if {@code csq} contained the four 256 * characters {@code "null"}. 257 * 258 * @param start 259 * The index of the first character in the subsequence 260 * 261 * @param end 262 * The index of the character following the last character in the 263 * subsequence 264 * 265 * @return This writer 266 * 267 * @throws IndexOutOfBoundsException 268 * If {@code start} or {@code end} are negative, {@code start} 269 * is greater than {@code end}, or {@code end} is greater than 270 * {@code csq.length()} 271 * 272 * @throws IOException 273 * If an I/O error occurs 274 * 275 * @since 1.5 276 */ 277 public Writer append(CharSequence csq, int start, int end) throws IOException { 278 if (csq == null) csq = "null"; 279 return append(csq.subSequence(start, end)); 280 } 281 282 /** 283 * Appends the specified character to this writer. 284 * 285 * <p> An invocation of this method of the form {@code out.append(c)} 286 * behaves in exactly the same way as the invocation 287 * 288 * <pre> 289 * out.write(c) </pre> 290 * 291 * @param c 292 * The 16-bit character to append 293 * 294 * @return This writer 295 * 296 * @throws IOException 297 * If an I/O error occurs 298 * 299 * @since 1.5 300 */ 301 public Writer append(char c) throws IOException { 302 write(c); 303 return this; 304 } 305 306 /** 307 * Flushes the stream. If the stream has saved any characters from the 308 * various write() methods in a buffer, write them immediately to their 309 * intended destination. Then, if that destination is another character or 310 * byte stream, flush it. Thus one flush() invocation will flush all the 311 * buffers in a chain of Writers and OutputStreams. 312 * 313 * <p> If the intended destination of this stream is an abstraction provided 314 * by the underlying operating system, for example a file, then flushing the 315 * stream guarantees only that bytes previously written to the stream are 316 * passed to the operating system for writing; it does not guarantee that 317 * they are actually written to a physical device such as a disk drive. 318 * 319 * @throws IOException 320 * If an I/O error occurs 321 */ 322 public abstract void flush() throws IOException; 323 324 /** 325 * Closes the stream, flushing it first. Once the stream has been closed, 326 * further write() or flush() invocations will cause an IOException to be 327 * thrown. Closing a previously closed stream has no effect. 328 * 329 * @throws IOException 330 * If an I/O error occurs 331 */ 332 public abstract void close() throws IOException; 333 334 }