1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package java.io; 19 20import java.util.Arrays; 21 22/** 23 * A specialized {@link Writer} that writes characters to a {@code StringBuffer} 24 * in a sequential manner, appending them in the process. The result can later 25 * be queried using the {@link #StringWriter(int)} or {@link #toString()} 26 * methods. 27 * 28 * @see StringReader 29 */ 30public class StringWriter extends Writer { 31 32 private StringBuffer buf; 33 34 /** 35 * Constructs a new {@code StringWriter} which has a {@link StringBuffer} 36 * allocated with the default size of 16 characters. The {@code 37 * StringBuffer} is also the {@code lock} used to synchronize access to this 38 * writer. 39 */ 40 public StringWriter() { 41 buf = new StringBuffer(16); 42 lock = buf; 43 } 44 45 /** 46 * Constructs a new {@code StringWriter} which has a {@link StringBuffer} 47 * allocated with a size of {@code initialSize} characters. The {@code 48 * StringBuffer} is also the {@code lock} used to synchronize access to this 49 * writer. 50 * 51 * @param initialSize 52 * the initial size of the target string buffer. 53 */ 54 public StringWriter(int initialSize) { 55 if (initialSize < 0) { 56 throw new IllegalArgumentException("initialSize < 0: " + initialSize); 57 } 58 buf = new StringBuffer(initialSize); 59 lock = buf; 60 } 61 62 /** 63 * Calling this method has no effect. In contrast to most {@code Writer} subclasses, 64 * the other methods in {@code StringWriter} do not throw an {@code IOException} if 65 * {@code close()} has been called. 66 * 67 * @throws IOException 68 * if an error occurs while closing this writer. 69 */ 70 @Override 71 public void close() throws IOException { 72 /* empty */ 73 } 74 75 /** 76 * Calling this method has no effect. 77 */ 78 @Override 79 public void flush() { 80 /* empty */ 81 } 82 83 /** 84 * Gets a reference to this writer's internal {@link StringBuffer}. Any 85 * changes made to the returned buffer are reflected in this writer. 86 * 87 * @return a reference to this writer's internal {@code StringBuffer}. 88 */ 89 public StringBuffer getBuffer() { 90 return buf; 91 } 92 93 /** 94 * Gets a copy of the contents of this writer as a string. 95 * 96 * @return this writer's contents as a string. 97 */ 98 @Override 99 public String toString() { 100 return buf.toString(); 101 } 102 103 /** 104 * Writes {@code count} characters starting at {@code offset} in {@code buf} 105 * to this writer's {@code StringBuffer}. 106 * 107 * @param chars 108 * the non-null character array to write. 109 * @param offset 110 * the index of the first character in {@code chars} to write. 111 * @param count 112 * the maximum number of characters to write. 113 * @throws IndexOutOfBoundsException 114 * if {@code offset < 0} or {@code count < 0}, or if {@code 115 * offset + count} is greater than the size of {@code buf}. 116 */ 117 @Override 118 public void write(char[] chars, int offset, int count) { 119 Arrays.checkOffsetAndCount(chars.length, offset, count); 120 if (count == 0) { 121 return; 122 } 123 buf.append(chars, offset, count); 124 } 125 126 /** 127 * Writes one character to this writer's {@code StringBuffer}. Only the two 128 * least significant bytes of the integer {@code oneChar} are written. 129 * 130 * @param oneChar 131 * the character to write to this writer's {@code StringBuffer}. 132 */ 133 @Override 134 public void write(int oneChar) { 135 buf.append((char) oneChar); 136 } 137 138 /** 139 * Writes the characters from the specified string to this writer's {@code 140 * StringBuffer}. 141 * 142 * @param str 143 * the non-null string containing the characters to write. 144 */ 145 @Override 146 public void write(String str) { 147 buf.append(str); 148 } 149 150 /** 151 * Writes {@code count} characters from {@code str} starting at {@code 152 * offset} to this writer's {@code StringBuffer}. 153 * 154 * @param str 155 * the non-null string containing the characters to write. 156 * @param offset 157 * the index of the first character in {@code str} to write. 158 * @param count 159 * the number of characters from {@code str} to write. 160 * @throws StringIndexOutOfBoundsException 161 * if {@code offset < 0} or {@code count < 0}, or if {@code 162 * offset + count} is greater than the length of {@code str}. 163 */ 164 @Override 165 public void write(String str, int offset, int count) { 166 String sub = str.substring(offset, offset + count); 167 buf.append(sub); 168 } 169 170 /** 171 * Appends the character {@code c} to this writer's {@code StringBuffer}. 172 * This method works the same way as {@link #write(int)}. 173 * 174 * @param c 175 * the character to append to the target stream. 176 * @return this writer. 177 */ 178 @Override 179 public StringWriter append(char c) { 180 write(c); 181 return this; 182 } 183 184 /** 185 * Appends the character sequence {@code csq} to this writer's {@code 186 * StringBuffer}. This method works the same way as {@code 187 * StringWriter.write(csq.toString())}. If {@code csq} is {@code null}, then 188 * the string "null" is written to the target stream. 189 * 190 * @param csq 191 * the character sequence appended to the target. 192 * @return this writer. 193 */ 194 @Override 195 public StringWriter append(CharSequence csq) { 196 if (csq == null) { 197 csq = "null"; 198 } 199 write(csq.toString()); 200 return this; 201 } 202 203 /** 204 * Appends a subsequence of the character sequence {@code csq} to this 205 * writer's {@code StringBuffer}. This method works the same way as {@code 206 * StringWriter.writer(csq.subsequence(start, end).toString())}. If {@code 207 * csq} is {@code null}, then the specified subsequence of the string "null" 208 * will be written to the target. 209 * 210 * @param csq 211 * the character sequence appended to the target. 212 * @param start 213 * the index of the first char in the character sequence appended 214 * to the target. 215 * @param end 216 * the index of the character following the last character of the 217 * subsequence appended to the target. 218 * @return this writer. 219 * @throws IndexOutOfBoundsException 220 * if {@code start > end}, {@code start < 0}, {@code end < 0} or 221 * either {@code start} or {@code end} are greater or equal than 222 * the length of {@code csq}. 223 */ 224 @Override 225 public StringWriter append(CharSequence csq, int start, int end) { 226 if (csq == null) { 227 csq = "null"; 228 } 229 String output = csq.subSequence(start, end).toString(); 230 write(output, 0, output.length()); 231 return this; 232 } 233} 234