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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 175 public CharArrayWriter append(CharSequence csq) { 176 String s = (csq == null ? "null" : csq.toString()); 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 */ 214 public CharArrayWriter append(CharSequence csq, int start, int end) { 215 String s = (csq == null ? "null" : csq).subSequence(start, end).toString(); 216 write(s, 0, s.length()); 217 return this; 218 } 219 220 /** 221 * Appends the specified character to this writer. 222 * 223 * <p> An invocation of this method of the form {@code out.append(c)} 224 * behaves in exactly the same way as the invocation 225 * 226 * <pre> 227 * out.write(c) </pre> 228 * 229 * @param c 230 * The 16-bit character to append 231 * 232 * @return This writer 233 * 234 * @since 1.5 235 */ 236 public CharArrayWriter append(char c) { 237 write(c); 238 return this; 239 } 240 241 /** 242 * Resets the buffer so that you can use it again without 243 * throwing away the already allocated buffer. 244 */ 245 public void reset() { 246 count = 0; 247 } 248 249 /** 250 * Returns a copy of the input data. 251 * 252 * @return an array of chars copied from the input data. 253 */ 254 public char toCharArray()[] { 255 synchronized (lock) { 256 return Arrays.copyOf(buf, count); 257 } 258 } 259 260 /** 261 * Returns the current size of the buffer. 262 * 263 * @return an int representing the current size of the buffer. 264 */ 265 public int size() { 266 return count; 267 } 268 269 /** 270 * Converts input data to a string. 271 * @return the string. 272 */ 273 public String toString() { 274 synchronized (lock) { 275 return new String(buf, 0, count); 276 } 277 } 278 279 /** 280 * Flush the stream. 281 */ 282 public void flush() { } 283 284 /** 285 * Close the stream. This method does not release the buffer, since its 286 * contents might still be required. Note: Invoking this method in this class 287 * will have no effect. 288 */ 289 public void close() { } 290 291 }