FastPrintWriter.java revision 8c84109b9fbbf473b225707a38261ff5f99d95fb
1b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onoratopackage com.android.internal.util; 2b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato 3b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onoratoimport java.io.IOException; 4b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onoratoimport java.io.OutputStream; 5b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onoratoimport java.io.PrintWriter; 6b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onoratoimport java.io.UnsupportedEncodingException; 7b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onoratoimport java.io.Writer; 8b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onoratoimport java.nio.ByteBuffer; 9b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onoratoimport java.nio.CharBuffer; 10b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onoratoimport java.nio.charset.Charset; 11b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onoratoimport java.nio.charset.CharsetEncoder; 12b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onoratoimport java.nio.charset.CoderResult; 13b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onoratoimport java.nio.charset.CodingErrorAction; 14b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato 15b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onoratopublic class FastPrintWriter extends PrintWriter { 16b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato private static Writer sDummyWriter = new Writer() { 17290bb011c5c1a9ba1f2116810b06cf52a9c36b3eJoe Onorato @Override 18290bb011c5c1a9ba1f2116810b06cf52a9c36b3eJoe Onorato public void close() throws IOException { 19290bb011c5c1a9ba1f2116810b06cf52a9c36b3eJoe Onorato UnsupportedOperationException ex 20b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato = new UnsupportedOperationException("Shouldn't be here"); 21ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe throw ex; 22b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato } 23b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian 24b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato @Override 25b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato public void flush() throws IOException { 26b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato close(); 27b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato } 2858b8b24256bdc2b613b7fda9151845ed9898a4c7Ashok Bhat 2906290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato @Override 3006290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato public void write(char[] buf, int offset, int count) throws IOException { 3158b8b24256bdc2b613b7fda9151845ed9898a4c7Ashok Bhat close(); 3206290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato } 3306290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato }; 3406290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato 3558b8b24256bdc2b613b7fda9151845ed9898a4c7Ashok Bhat private final int mBufferLen; 3606290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato private final char[] mText; 3706290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato private int mPos; 3806290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato 3906290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato final private OutputStream mOutputStream; 4058b8b24256bdc2b613b7fda9151845ed9898a4c7Ashok Bhat final private boolean mAutoFlush; 4158b8b24256bdc2b613b7fda9151845ed9898a4c7Ashok Bhat final private String mSeparator; 4223ecae3bbb60c5af940f3a22170d75eb6ac05b69Joe Onorato 43b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato final private Writer mWriter; 44b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato 45b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato private CharsetEncoder mCharset; 46b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato final private ByteBuffer mBytes; 47a3804cf77f0edd93f6247a055cdafb856b117eecElliott Hughes 48a3804cf77f0edd93f6247a055cdafb856b117eecElliott Hughes private boolean mIoError; 49d2110dbce071a236b6176de344ca797b737542ebJoe Onorato 50b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato /** 51b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * Constructs a new {@code PrintWriter} with {@code out} as its target 52b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * stream. By default, the new print writer does not automatically flush its 53b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * contents to the target stream when a newline is encountered. 54b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * 55b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * @param out 56b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * the target output stream. 5723ecae3bbb60c5af940f3a22170d75eb6ac05b69Joe Onorato * @throws NullPointerException 5823ecae3bbb60c5af940f3a22170d75eb6ac05b69Joe Onorato * if {@code out} is {@code null}. 5923ecae3bbb60c5af940f3a22170d75eb6ac05b69Joe Onorato */ 6023ecae3bbb60c5af940f3a22170d75eb6ac05b69Joe Onorato public FastPrintWriter(OutputStream out) { 6123ecae3bbb60c5af940f3a22170d75eb6ac05b69Joe Onorato this(out, false, 8192); 6223ecae3bbb60c5af940f3a22170d75eb6ac05b69Joe Onorato } 6323ecae3bbb60c5af940f3a22170d75eb6ac05b69Joe Onorato 64b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato /** 65b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * Constructs a new {@code PrintWriter} with {@code out} as its target 66b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * stream. The parameter {@code autoFlush} determines if the print writer 67b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * automatically flushes its contents to the target stream when a newline is 68b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * encountered. 6923ecae3bbb60c5af940f3a22170d75eb6ac05b69Joe Onorato * 7023ecae3bbb60c5af940f3a22170d75eb6ac05b69Joe Onorato * @param out 7123ecae3bbb60c5af940f3a22170d75eb6ac05b69Joe Onorato * the target output stream. 7223ecae3bbb60c5af940f3a22170d75eb6ac05b69Joe Onorato * @param autoFlush 7323ecae3bbb60c5af940f3a22170d75eb6ac05b69Joe Onorato * indicates whether contents are flushed upon encountering a 74b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * newline sequence. 7558b8b24256bdc2b613b7fda9151845ed9898a4c7Ashok Bhat * @throws NullPointerException 76b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * if {@code out} is {@code null}. 77b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato */ 7806290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato public FastPrintWriter(OutputStream out, boolean autoFlush) { 7958b8b24256bdc2b613b7fda9151845ed9898a4c7Ashok Bhat this(out, autoFlush, 8192); 8058b8b24256bdc2b613b7fda9151845ed9898a4c7Ashok Bhat } 8106290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato 8206290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato /** 8306290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato * Constructs a new {@code PrintWriter} with {@code out} as its target 8406290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato * stream and a custom buffer size. The parameter {@code autoFlush} determines 8506290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato * if the print writer automatically flushes its contents to the target stream 8606290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato * when a newline is encountered. 8706290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato * 8806290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato * @param out 8906290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato * the target output stream. 9006290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato * @param autoFlush 9106290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato * indicates whether contents are flushed upon encountering a 9206290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato * newline sequence. 9358b8b24256bdc2b613b7fda9151845ed9898a4c7Ashok Bhat * @param bufferLen 9406290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato * specifies the size of the FastPrintWriter's internal buffer; the 9506290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato * default is 8192. 9658b8b24256bdc2b613b7fda9151845ed9898a4c7Ashok Bhat * @throws NullPointerException 9758b8b24256bdc2b613b7fda9151845ed9898a4c7Ashok Bhat * if {@code out} is {@code null}. 9806290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato */ 9906290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato public FastPrintWriter(OutputStream out, boolean autoFlush, int bufferLen) { 10006290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato super(sDummyWriter, autoFlush); 10106290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato if (out == null) { 102a3804cf77f0edd93f6247a055cdafb856b117eecElliott Hughes throw new NullPointerException("out is null"); 10306290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato } 10406290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato mBufferLen = bufferLen; 10506290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato mText = new char[bufferLen]; 10658b8b24256bdc2b613b7fda9151845ed9898a4c7Ashok Bhat mBytes = ByteBuffer.allocate(mBufferLen); 10706290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato mOutputStream = out; 10806290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato mWriter = null; 109b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato mAutoFlush = autoFlush; 11058b8b24256bdc2b613b7fda9151845ed9898a4c7Ashok Bhat mSeparator = System.lineSeparator(); 11158b8b24256bdc2b613b7fda9151845ed9898a4c7Ashok Bhat initDefaultEncoder(); 112b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato } 11358b8b24256bdc2b613b7fda9151845ed9898a4c7Ashok Bhat 11423ecae3bbb60c5af940f3a22170d75eb6ac05b69Joe Onorato /** 11558b8b24256bdc2b613b7fda9151845ed9898a4c7Ashok Bhat * Constructs a new {@code PrintWriter} with {@code wr} as its target 11658b8b24256bdc2b613b7fda9151845ed9898a4c7Ashok Bhat * writer. By default, the new print writer does not automatically flush its 117b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * contents to the target writer when a newline is encountered. 118b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * 11906290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato * <p>NOTE: Unlike PrintWriter, this version will still do buffering inside of 120b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * FastPrintWriter before sending data to the Writer. This means you must call 121ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe * flush() before retrieving any data from the Writer.</p> 122b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * 123b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * @param wr 124b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * the target writer. 125b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * @throws NullPointerException 126 * if {@code wr} is {@code null}. 127 */ 128 public FastPrintWriter(Writer wr) { 129 this(wr, false, 8192); 130 } 131 132 /** 133 * Constructs a new {@code PrintWriter} with {@code out} as its target 134 * writer. The parameter {@code autoFlush} determines if the print writer 135 * automatically flushes its contents to the target writer when a newline is 136 * encountered. 137 * 138 * @param wr 139 * the target writer. 140 * @param autoFlush 141 * indicates whether to flush contents upon encountering a 142 * newline sequence. 143 * @throws NullPointerException 144 * if {@code out} is {@code null}. 145 */ 146 public FastPrintWriter(Writer wr, boolean autoFlush) { 147 this(wr, autoFlush, 8192); 148 } 149 150 /** 151 * Constructs a new {@code PrintWriter} with {@code out} as its target 152 * writer and a custom buffer size. The parameter {@code autoFlush} determines 153 * if the print writer automatically flushes its contents to the target writer 154 * when a newline is encountered. 155 * 156 * @param wr 157 * the target writer. 158 * @param autoFlush 159 * indicates whether to flush contents upon encountering a 160 * newline sequence. 161 * @param bufferLen 162 * specifies the size of the FastPrintWriter's internal buffer; the 163 * default is 8192. 164 * @throws NullPointerException 165 * if {@code wr} is {@code null}. 166 */ 167 public FastPrintWriter(Writer wr, boolean autoFlush, int bufferLen) { 168 super(sDummyWriter, autoFlush); 169 if (wr == null) { 170 throw new NullPointerException("wr is null"); 171 } 172 mBufferLen = bufferLen; 173 mText = new char[bufferLen]; 174 mBytes = null; 175 mOutputStream = null; 176 mWriter = wr; 177 mAutoFlush = autoFlush; 178 mSeparator = System.lineSeparator(); 179 initDefaultEncoder(); 180 } 181 182 private final void initEncoder(String csn) throws UnsupportedEncodingException { 183 try { 184 mCharset = Charset.forName(csn).newEncoder(); 185 } catch (Exception e) { 186 throw new UnsupportedEncodingException(csn); 187 } 188 mCharset.onMalformedInput(CodingErrorAction.REPLACE); 189 mCharset.onUnmappableCharacter(CodingErrorAction.REPLACE); 190 } 191 192 /** 193 * Flushes this writer and returns the value of the error flag. 194 * 195 * @return {@code true} if either an {@code IOException} has been thrown 196 * previously or if {@code setError()} has been called; 197 * {@code false} otherwise. 198 * @see #setError() 199 */ 200 public boolean checkError() { 201 flush(); 202 synchronized (lock) { 203 return mIoError; 204 } 205 } 206 207 /** 208 * Sets the error state of the stream to false. 209 * @since 1.6 210 */ 211 protected void clearError() { 212 synchronized (lock) { 213 mIoError = false; 214 } 215 } 216 217 /** 218 * Sets the error flag of this writer to true. 219 */ 220 protected void setError() { 221 synchronized (lock) { 222 mIoError = true; 223 } 224 } 225 226 private final void initDefaultEncoder() { 227 mCharset = Charset.defaultCharset().newEncoder(); 228 mCharset.onMalformedInput(CodingErrorAction.REPLACE); 229 mCharset.onUnmappableCharacter(CodingErrorAction.REPLACE); 230 } 231 232 private void appendLocked(char c) throws IOException { 233 int pos = mPos; 234 if (pos >= (mBufferLen-1)) { 235 flushLocked(); 236 pos = mPos; 237 } 238 mText[pos] = c; 239 mPos = pos+1; 240 } 241 242 private void appendLocked(String str, int i, final int length) throws IOException { 243 final int BUFFER_LEN = mBufferLen; 244 if (length > BUFFER_LEN) { 245 final int end = i + length; 246 while (i < end) { 247 int next = i + BUFFER_LEN; 248 appendLocked(str, i, next < end ? BUFFER_LEN : (end - i)); 249 i = next; 250 } 251 return; 252 } 253 int pos = mPos; 254 if ((pos+length) > BUFFER_LEN) { 255 flushLocked(); 256 pos = mPos; 257 } 258 str.getChars(i, i + length, mText, pos); 259 mPos = pos + length; 260 } 261 262 private void appendLocked(char[] buf, int i, final int length) throws IOException { 263 final int BUFFER_LEN = mBufferLen; 264 if (length > BUFFER_LEN) { 265 final int end = i + length; 266 while (i < end) { 267 int next = i + BUFFER_LEN; 268 appendLocked(buf, i, next < end ? BUFFER_LEN : (end - i)); 269 i = next; 270 } 271 return; 272 } 273 int pos = mPos; 274 if ((pos+length) > BUFFER_LEN) { 275 flushLocked(); 276 pos = mPos; 277 } 278 System.arraycopy(buf, i, mText, pos, length); 279 mPos = pos + length; 280 } 281 282 private void flushBytesLocked() throws IOException { 283 int position; 284 if ((position = mBytes.position()) > 0) { 285 mBytes.flip(); 286 mOutputStream.write(mBytes.array(), 0, position); 287 mBytes.clear(); 288 } 289 } 290 291 private void flushLocked() throws IOException { 292 //Log.i("PackageManager", "flush mPos=" + mPos); 293 if (mPos > 0) { 294 if (mOutputStream != null) { 295 CharBuffer charBuffer = CharBuffer.wrap(mText, 0, mPos); 296 CoderResult result = mCharset.encode(charBuffer, mBytes, true); 297 while (true) { 298 if (result.isError()) { 299 throw new IOException(result.toString()); 300 } else if (result.isOverflow()) { 301 flushBytesLocked(); 302 result = mCharset.encode(charBuffer, mBytes, true); 303 continue; 304 } 305 break; 306 } 307 flushBytesLocked(); 308 mOutputStream.flush(); 309 } else { 310 mWriter.write(mText, 0, mPos); 311 mWriter.flush(); 312 } 313 mPos = 0; 314 } 315 } 316 317 /** 318 * Ensures that all pending data is sent out to the target. It also 319 * flushes the target. If an I/O error occurs, this writer's error 320 * state is set to {@code true}. 321 */ 322 @Override 323 public void flush() { 324 synchronized (lock) { 325 try { 326 flushLocked(); 327 if (mOutputStream != null) { 328 mOutputStream.flush(); 329 } else { 330 mWriter.flush(); 331 } 332 } catch (IOException e) { 333 setError(); 334 } 335 } 336 } 337 338 @Override 339 public void close() { 340 synchronized (lock) { 341 try { 342 flushLocked(); 343 if (mOutputStream != null) { 344 mOutputStream.close(); 345 } else { 346 mWriter.close(); 347 } 348 } catch (IOException e) { 349 setError(); 350 } 351 } 352 } 353 354 /** 355 * Prints the string representation of the specified character array 356 * to the target. 357 * 358 * @param charArray 359 * the character array to print to the target. 360 * @see #print(String) 361 */ 362 public void print(char[] charArray) { 363 synchronized (lock) { 364 try { 365 appendLocked(charArray, 0, charArray.length); 366 } catch (IOException e) { 367 } 368 } 369 } 370 371 /** 372 * Prints the string representation of the specified character to the 373 * target. 374 * 375 * @param ch 376 * the character to print to the target. 377 * @see #print(String) 378 */ 379 public void print(char ch) { 380 synchronized (lock) { 381 try { 382 appendLocked(ch); 383 } catch (IOException e) { 384 } 385 } 386 } 387 388 /** 389 * Prints a string to the target. The string is converted to an array of 390 * bytes using the encoding chosen during the construction of this writer. 391 * The bytes are then written to the target with {@code write(int)}. 392 * <p> 393 * If an I/O error occurs, this writer's error flag is set to {@code true}. 394 * 395 * @param str 396 * the string to print to the target. 397 * @see #write(int) 398 */ 399 public void print(String str) { 400 if (str == null) { 401 str = String.valueOf((Object) null); 402 } 403 synchronized (lock) { 404 try { 405 appendLocked(str, 0, str.length()); 406 } catch (IOException e) { 407 setError(); 408 } 409 } 410 } 411 412 413 @Override 414 public void print(int inum) { 415 if (inum == 0) { 416 print("0"); 417 } else { 418 super.print(inum); 419 } 420 } 421 422 @Override 423 public void print(long lnum) { 424 if (lnum == 0) { 425 print("0"); 426 } else { 427 super.print(lnum); 428 } 429 } 430 431 /** 432 * Prints a newline. Flushes this writer if the autoFlush flag is set to {@code true}. 433 */ 434 public void println() { 435 synchronized (lock) { 436 try { 437 appendLocked(mSeparator, 0, mSeparator.length()); 438 if (mAutoFlush) { 439 flushLocked(); 440 } 441 } catch (IOException e) { 442 setError(); 443 } 444 } 445 } 446 447 @Override 448 public void println(int inum) { 449 if (inum == 0) { 450 println("0"); 451 } else { 452 super.println(inum); 453 } 454 } 455 456 @Override 457 public void println(long lnum) { 458 if (lnum == 0) { 459 println("0"); 460 } else { 461 super.print(lnum); 462 } 463 } 464 465 /** 466 * Prints the string representation of the character array {@code chars} followed by a newline. 467 * Flushes this writer if the autoFlush flag is set to {@code true}. 468 */ 469 public void println(char[] chars) { 470 print(chars); 471 println(); 472 } 473 474 /** 475 * Prints the string representation of the char {@code c} followed by a newline. 476 * Flushes this writer if the autoFlush flag is set to {@code true}. 477 */ 478 public void println(char c) { 479 print(c); 480 println(); 481 } 482 483 /** 484 * Writes {@code count} characters from {@code buffer} starting at {@code 485 * offset} to the target. 486 * <p> 487 * This writer's error flag is set to {@code true} if this writer is closed 488 * or an I/O error occurs. 489 * 490 * @param buf 491 * the buffer to write to the target. 492 * @param offset 493 * the index of the first character in {@code buffer} to write. 494 * @param count 495 * the number of characters in {@code buffer} to write. 496 * @throws IndexOutOfBoundsException 497 * if {@code offset < 0} or {@code count < 0}, or if {@code 498 * offset + count} is greater than the length of {@code buf}. 499 */ 500 @Override 501 public void write(char[] buf, int offset, int count) { 502 synchronized (lock) { 503 try { 504 appendLocked(buf, offset, count); 505 } catch (IOException e) { 506 } 507 } 508 } 509 510 /** 511 * Writes one character to the target. Only the two least significant bytes 512 * of the integer {@code oneChar} are written. 513 * <p> 514 * This writer's error flag is set to {@code true} if this writer is closed 515 * or an I/O error occurs. 516 * 517 * @param oneChar 518 * the character to write to the target. 519 */ 520 @Override 521 public void write(int oneChar) { 522 synchronized (lock) { 523 try { 524 appendLocked((char) oneChar); 525 } catch (IOException e) { 526 } 527 } 528 } 529 530 /** 531 * Writes the characters from the specified string to the target. 532 * 533 * @param str 534 * the non-null string containing the characters to write. 535 */ 536 @Override 537 public void write(String str) { 538 synchronized (lock) { 539 try { 540 appendLocked(str, 0, str.length()); 541 } catch (IOException e) { 542 } 543 } 544 } 545 546 /** 547 * Writes {@code count} characters from {@code str} starting at {@code 548 * offset} to the target. 549 * 550 * @param str 551 * the non-null string containing the characters to write. 552 * @param offset 553 * the index of the first character in {@code str} to write. 554 * @param count 555 * the number of characters from {@code str} to write. 556 * @throws IndexOutOfBoundsException 557 * if {@code offset < 0} or {@code count < 0}, or if {@code 558 * offset + count} is greater than the length of {@code str}. 559 */ 560 @Override 561 public void write(String str, int offset, int count) { 562 synchronized (lock) { 563 try { 564 appendLocked(str, offset, count); 565 } catch (IOException e) { 566 } 567 } 568 } 569 570 /** 571 * Appends a subsequence of the character sequence {@code csq} to the 572 * target. This method works the same way as {@code 573 * PrintWriter.print(csq.subsequence(start, end).toString())}. If {@code 574 * csq} is {@code null}, then the specified subsequence of the string "null" 575 * will be written to the target. 576 * 577 * @param csq 578 * the character sequence appended to the target. 579 * @param start 580 * the index of the first char in the character sequence appended 581 * to the target. 582 * @param end 583 * the index of the character following the last character of the 584 * subsequence appended to the target. 585 * @return this writer. 586 * @throws StringIndexOutOfBoundsException 587 * if {@code start > end}, {@code start < 0}, {@code end < 0} or 588 * either {@code start} or {@code end} are greater or equal than 589 * the length of {@code csq}. 590 */ 591 @Override 592 public PrintWriter append(CharSequence csq, int start, int end) { 593 if (csq == null) { 594 csq = "null"; 595 } 596 String output = csq.subSequence(start, end).toString(); 597 write(output, 0, output.length()); 598 return this; 599 } 600} 601