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 import java.util.Arrays; 29 30 /** 31 * This class implements a character buffer that can be used as an Writer. 32 * The buffer automatically grows when data is written to the stream. The data 33 * can be retrieved using toCharArray() and toString(). 34 * <P> 35 * Note: Invoking close() on this class has no effect, and methods 36 * of this class can be called after the stream has closed 37 * without generating an IOException. 38 * 39 * @author Herb Jellinek 40 * @since 1.1 41 */ 42 public 43 class CharArrayWriter extends Writer { 44 /** 45 * The buffer where data is stored. 46 */ 47 protected char buf[]; 48 49 /** 50 * The number of chars in the buffer. 51 */ 52 protected int count; 53 54 /** 55 * Creates a new CharArrayWriter. 56 */ CharArrayWriter()57 public CharArrayWriter() { 58 this(32); 59 } 60 61 /** 62 * Creates a new CharArrayWriter with the specified initial size. 63 * 64 * @param initialSize an int specifying the initial buffer size. 65 * @exception IllegalArgumentException if initialSize is negative 66 */ CharArrayWriter(int initialSize)67 public CharArrayWriter(int initialSize) { 68 if (initialSize < 0) { 69 throw new IllegalArgumentException("Negative initial size: " 70 + initialSize); 71 } 72 buf = new char[initialSize]; 73 } 74 75 /** 76 * Writes a character to the buffer. 77 */ write(int c)78 public void write(int c) { 79 synchronized (lock) { 80 int newcount = count + 1; 81 if (newcount > buf.length) { 82 buf = Arrays.copyOf(buf, Math.max(buf.length << 1, newcount)); 83 } 84 buf[count] = (char)c; 85 count = newcount; 86 } 87 } 88 89 /** 90 * Writes characters to the buffer. 91 * @param c the data to be written 92 * @param off the start offset in the data 93 * @param len the number of chars that are written 94 * 95 * @throws IndexOutOfBoundsException 96 * If {@code off} is negative, or {@code len} is negative, 97 * or {@code off + len} is negative or greater than the length 98 * of the given array 99 */ write(char c[], int off, int len)100 public void write(char c[], int off, int len) { 101 if ((off < 0) || (off > c.length) || (len < 0) || 102 ((off + len) > c.length) || ((off + len) < 0)) { 103 throw new IndexOutOfBoundsException(); 104 } else if (len == 0) { 105 return; 106 } 107 synchronized (lock) { 108 int newcount = count + len; 109 if (newcount > buf.length) { 110 buf = Arrays.copyOf(buf, Math.max(buf.length << 1, newcount)); 111 } 112 System.arraycopy(c, off, buf, count, len); 113 count = newcount; 114 } 115 } 116 117 /** 118 * Write a portion of a string to the buffer. 119 * @param str String to be written from 120 * @param off Offset from which to start reading characters 121 * @param len Number of characters to be written 122 * 123 * @throws IndexOutOfBoundsException 124 * If {@code off} is negative, or {@code len} is negative, 125 * or {@code off + len} is negative or greater than the length 126 * of the given string 127 */ write(String str, int off, int len)128 public void write(String str, int off, int len) { 129 synchronized (lock) { 130 int newcount = count + len; 131 if (newcount > buf.length) { 132 buf = Arrays.copyOf(buf, Math.max(buf.length << 1, newcount)); 133 } 134 str.getChars(off, off + len, buf, count); 135 count = newcount; 136 } 137 } 138 139 /** 140 * Writes the contents of the buffer to another character stream. 141 * 142 * @param out the output stream to write to 143 * @throws IOException If an I/O error occurs. 144 */ writeTo(Writer out)145 public void writeTo(Writer out) throws IOException { 146 synchronized (lock) { 147 out.write(buf, 0, count); 148 } 149 } 150 151 /** 152 * Appends the specified character sequence to this writer. 153 * 154 * <p> An invocation of this method of the form {@code out.append(csq)} 155 * behaves in exactly the same way as the invocation 156 * 157 * <pre> 158 * out.write(csq.toString()) </pre> 159 * 160 * <p> Depending on the specification of {@code toString} for the 161 * character sequence {@code csq}, the entire sequence may not be 162 * appended. For instance, invoking the {@code toString} method of a 163 * character buffer will return a subsequence whose content depends upon 164 * the buffer's position and limit. 165 * 166 * @param csq 167 * The character sequence to append. If {@code csq} is 168 * {@code null}, then the four characters {@code "null"} are 169 * appended to this writer. 170 * 171 * @return This writer 172 * 173 * @since 1.5 174 */ append(CharSequence csq)175 public CharArrayWriter append(CharSequence csq) { 176 String s = String.valueOf(csq); 177 write(s, 0, s.length()); 178 return this; 179 } 180 181 /** 182 * Appends a subsequence of the specified character sequence to this writer. 183 * 184 * <p> An invocation of this method of the form 185 * {@code out.append(csq, start, end)} when 186 * {@code csq} is not {@code null}, behaves in 187 * exactly the same way as the invocation 188 * 189 * <pre> 190 * out.write(csq.subSequence(start, end).toString()) </pre> 191 * 192 * @param csq 193 * The character sequence from which a subsequence will be 194 * appended. If {@code csq} is {@code null}, then characters 195 * will be appended as if {@code csq} contained the four 196 * characters {@code "null"}. 197 * 198 * @param start 199 * The index of the first character in the subsequence 200 * 201 * @param end 202 * The index of the character following the last character in the 203 * subsequence 204 * 205 * @return This writer 206 * 207 * @throws IndexOutOfBoundsException 208 * If {@code start} or {@code end} are negative, {@code start} 209 * is greater than {@code end}, or {@code end} is greater than 210 * {@code csq.length()} 211 * 212 * @since 1.5 213 */ append(CharSequence csq, int start, int end)214 public CharArrayWriter append(CharSequence csq, int start, int end) { 215 if (csq == null) csq = "null"; 216 return append(csq.subSequence(start, end)); 217 } 218 219 /** 220 * Appends the specified character to this writer. 221 * 222 * <p> An invocation of this method of the form {@code out.append(c)} 223 * behaves in exactly the same way as the invocation 224 * 225 * <pre> 226 * out.write(c) </pre> 227 * 228 * @param c 229 * The 16-bit character to append 230 * 231 * @return This writer 232 * 233 * @since 1.5 234 */ append(char c)235 public CharArrayWriter append(char c) { 236 write(c); 237 return this; 238 } 239 240 /** 241 * Resets the buffer so that you can use it again without 242 * throwing away the already allocated buffer. 243 */ reset()244 public void reset() { 245 count = 0; 246 } 247 248 /** 249 * Returns a copy of the input data. 250 * 251 * @return an array of chars copied from the input data. 252 */ toCharArray()253 public char[] toCharArray() { 254 synchronized (lock) { 255 return Arrays.copyOf(buf, count); 256 } 257 } 258 259 /** 260 * Returns the current size of the buffer. 261 * 262 * @return an int representing the current size of the buffer. 263 */ size()264 public int size() { 265 return count; 266 } 267 268 /** 269 * Converts input data to a string. 270 * @return the string. 271 */ toString()272 public String toString() { 273 synchronized (lock) { 274 return new String(buf, 0, count); 275 } 276 } 277 278 /** 279 * Flush the stream. 280 */ flush()281 public void flush() { } 282 283 /** 284 * Close the stream. This method does not release the buffer, since its 285 * contents might still be required. Note: Invoking this method in this class 286 * will have no effect. 287 */ close()288 public void close() { } 289 290 } 291