1. /*
  2. * @(#)Writer.java 1.26 04/07/16
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.io;
  8. /**
  9. * Abstract class for writing to character streams. The only methods that a
  10. * subclass must implement are write(char[], int, int), flush(), and close().
  11. * Most subclasses, however, will override some of the methods defined here in
  12. * order to provide higher efficiency, additional functionality, or both.
  13. *
  14. * @see Writer
  15. * @see BufferedWriter
  16. * @see CharArrayWriter
  17. * @see FilterWriter
  18. * @see OutputStreamWriter
  19. * @see FileWriter
  20. * @see PipedWriter
  21. * @see PrintWriter
  22. * @see StringWriter
  23. * @see Reader
  24. *
  25. * @version 1.26, 04/07/16
  26. * @author Mark Reinhold
  27. * @since JDK1.1
  28. */
  29. public abstract class Writer implements Appendable, Closeable, Flushable {
  30. /**
  31. * Temporary buffer used to hold writes of strings and single characters
  32. */
  33. private char[] writeBuffer;
  34. /**
  35. * Size of writeBuffer, must be >= 1
  36. */
  37. private final int writeBufferSize = 1024;
  38. /**
  39. * The object used to synchronize operations on this stream. For
  40. * efficiency, a character-stream object may use an object other than
  41. * itself to protect critical sections. A subclass should therefore use
  42. * the object in this field rather than <tt>this</tt> or a synchronized
  43. * method.
  44. */
  45. protected Object lock;
  46. /**
  47. * Create a new character-stream writer whose critical sections will
  48. * synchronize on the writer itself.
  49. */
  50. protected Writer() {
  51. this.lock = this;
  52. }
  53. /**
  54. * Create a new character-stream writer whose critical sections will
  55. * synchronize on the given object.
  56. *
  57. * @param lock Object to synchronize on.
  58. */
  59. protected Writer(Object lock) {
  60. if (lock == null) {
  61. throw new NullPointerException();
  62. }
  63. this.lock = lock;
  64. }
  65. /**
  66. * Write a single character. The character to be written is contained in
  67. * the 16 low-order bits of the given integer value; the 16 high-order bits
  68. * are ignored.
  69. *
  70. * <p> Subclasses that intend to support efficient single-character output
  71. * should override this method.
  72. *
  73. * @param c int specifying a character to be written.
  74. * @exception IOException If an I/O error occurs
  75. */
  76. public void write(int c) throws IOException {
  77. synchronized (lock) {
  78. if (writeBuffer == null){
  79. writeBuffer = new char[writeBufferSize];
  80. }
  81. writeBuffer[0] = (char) c;
  82. write(writeBuffer, 0, 1);
  83. }
  84. }
  85. /**
  86. * Write an array of characters.
  87. *
  88. * @param cbuf Array of characters to be written
  89. *
  90. * @exception IOException If an I/O error occurs
  91. */
  92. public void write(char cbuf[]) throws IOException {
  93. write(cbuf, 0, cbuf.length);
  94. }
  95. /**
  96. * Write a portion of an array of characters.
  97. *
  98. * @param cbuf Array of characters
  99. * @param off Offset from which to start writing characters
  100. * @param len Number of characters to write
  101. *
  102. * @exception IOException If an I/O error occurs
  103. */
  104. abstract public void write(char cbuf[], int off, int len) throws IOException;
  105. /**
  106. * Write a string.
  107. *
  108. * @param str String to be written
  109. *
  110. * @exception IOException If an I/O error occurs
  111. */
  112. public void write(String str) throws IOException {
  113. write(str, 0, str.length());
  114. }
  115. /**
  116. * Write a portion of a string.
  117. *
  118. * @param str A String
  119. * @param off Offset from which to start writing characters
  120. * @param len Number of characters to write
  121. *
  122. * @exception IOException If an I/O error occurs
  123. */
  124. public void write(String str, int off, int len) throws IOException {
  125. synchronized (lock) {
  126. char cbuf[];
  127. if (len <= writeBufferSize) {
  128. if (writeBuffer == null) {
  129. writeBuffer = new char[writeBufferSize];
  130. }
  131. cbuf = writeBuffer;
  132. } else { // Don't permanently allocate very large buffers.
  133. cbuf = new char[len];
  134. }
  135. str.getChars(off, (off + len), cbuf, 0);
  136. write(cbuf, 0, len);
  137. }
  138. }
  139. /**
  140. * Appends the specified character sequence to this writer.
  141. *
  142. * <p> An invocation of this method of the form <tt>out.append(csq)</tt>
  143. * behaves in exactly the same way as the invocation
  144. *
  145. * <pre>
  146. * out.write(csq.toString()) </pre>
  147. *
  148. * <p> Depending on the specification of <tt>toString</tt> for the
  149. * character sequence <tt>csq</tt>, the entire sequence may not be
  150. * appended. For instance, invoking the <tt>toString</tt> method of a
  151. * character buffer will return a subsequence whose content depends upon
  152. * the buffer's position and limit.
  153. *
  154. * @param csq
  155. * The character sequence to append. If <tt>csq</tt> is
  156. * <tt>null</tt>, then the four characters <tt>"null"</tt> are
  157. * appended to this writer.
  158. *
  159. * @return This writer
  160. *
  161. * @throws IOException
  162. * If an I/O error occurs
  163. *
  164. * @since 1.5
  165. */
  166. public Writer append(CharSequence csq) throws IOException {
  167. if (csq == null)
  168. write("null");
  169. else
  170. write(csq.toString());
  171. return this;
  172. }
  173. /**
  174. * Appends a subsequence of the specified character sequence to this writer.
  175. * <tt>Appendable</tt>.
  176. *
  177. * <p> An invocation of this method of the form <tt>out.append(csq, start,
  178. * end)</tt> when <tt>csq</tt> is not <tt>null</tt> behaves in exactly the
  179. * same way as the invocation
  180. *
  181. * <pre>
  182. * out.write(csq.subSequence(start, end).toString()) </pre>
  183. *
  184. * @param csq
  185. * The character sequence from which a subsequence will be
  186. * appended. If <tt>csq</tt> is <tt>null</tt>, then characters
  187. * will be appended as if <tt>csq</tt> contained the four
  188. * characters <tt>"null"</tt>.
  189. *
  190. * @param start
  191. * The index of the first character in the subsequence
  192. *
  193. * @param end
  194. * The index of the character following the last character in the
  195. * subsequence
  196. *
  197. * @return This writer
  198. *
  199. * @throws IndexOutOfBoundsException
  200. * If <tt>start</tt> or <tt>end</tt> are negative, <tt>start</tt>
  201. * is greater than <tt>end</tt>, or <tt>end</tt> is greater than
  202. * <tt>csq.length()</tt>
  203. *
  204. * @throws IOException
  205. * If an I/O error occurs
  206. *
  207. * @since 1.5
  208. */
  209. public Writer append(CharSequence csq, int start, int end) throws IOException {
  210. CharSequence cs = (csq == null ? "null" : csq);
  211. write(cs.subSequence(start, end).toString());
  212. return this;
  213. }
  214. /**
  215. * Appends the specified character to this writer.
  216. *
  217. * <p> An invocation of this method of the form <tt>out.append(c)</tt>
  218. * behaves in exactly the same way as the invocation
  219. *
  220. * <pre>
  221. * out.write(c) </pre>
  222. *
  223. * @param c
  224. * The 16-bit character to append
  225. *
  226. * @return This writer
  227. *
  228. * @throws IOException
  229. * If an I/O error occurs
  230. *
  231. * @since 1.5
  232. */
  233. public Writer append(char c) throws IOException {
  234. write(c);
  235. return this;
  236. }
  237. /**
  238. * Flush the stream. If the stream has saved any characters from the
  239. * various write() methods in a buffer, write them immediately to their
  240. * intended destination. Then, if that destination is another character or
  241. * byte stream, flush it. Thus one flush() invocation will flush all the
  242. * buffers in a chain of Writers and OutputStreams.
  243. * <p>
  244. * If the intended destination of this stream is an abstraction provided by
  245. * the underlying operating system, for example a file, then flushing the
  246. * stream guarantees only that bytes previously written to the stream are
  247. * passed to the operating system for writing; it does not guarantee that
  248. * they are actually written to a physical device such as a disk drive.
  249. *
  250. * @exception IOException If an I/O error occurs
  251. */
  252. abstract public void flush() throws IOException;
  253. /**
  254. * Close the stream, flushing it first. Once a stream has been closed,
  255. * further write() or flush() invocations will cause an IOException to be
  256. * thrown. Closing a previously-closed stream, however, has no effect.
  257. *
  258. * @exception IOException If an I/O error occurs
  259. */
  260. abstract public void close() throws IOException;
  261. }