1 /* PrintStream.java -- OutputStream for printing output 2 Copyright (C) 1998, 1999, 2001, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. 3 4 This file is part of GNU Classpath. 5 6 GNU Classpath is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2, or (at your option) 9 any later version. 10 11 GNU Classpath is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GNU Classpath; see the file COPYING. If not, write to the 18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19 02110-1301 USA. 20 21 Linking this library statically or dynamically with other modules is 22 making a combined work based on this library. Thus, the terms and 23 conditions of the GNU General Public License cover the whole 24 combination. 25 26 As a special exception, the copyright holders of this library give you 27 permission to link this library with independent modules to produce an 28 executable, regardless of the license terms of these independent 29 modules, and to copy and distribute the resulting executable under 30 terms of your choice, provided that you also meet, for each linked 31 independent module, the terms and conditions of the license of that 32 module. An independent module is a module which is not derived from 33 or based on this library. If you modify this library, you may extend 34 this exception to your version of the library, but you are not 35 obligated to do so. If you do not wish to do so, delete this 36 exception statement from your version. */ 37 38 39 package java.io; 40 41 import java.util.Formatter; 42 import java.util.Locale; 43 44 import gnu.gcj.convert.UnicodeToBytes; 45 46 /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3 47 * "The Java Language Specification", ISBN 0-201-63451-1 48 * Status: Believed complete and correct to 1.3 49 */ 50 51 /** 52 * This class prints Java primitive values and object to a stream as 53 * text. None of the methods in this class throw an exception. However, 54 * errors can be detected by calling the <code>checkError()</code> method. 55 * Additionally, this stream can be designated as "autoflush" when 56 * created so that any writes are automatically flushed to the underlying 57 * output sink when the current line is terminated. 58 * <p> 59 * This class converts char's into byte's using the system default encoding. 60 * 61 * @author Aaron M. Renn (arenn@urbanophile.com) 62 * @author Tom Tromey (tromey@cygnus.com) 63 */ 64 public class PrintStream extends FilterOutputStream implements Appendable 65 { 66 /* Notice the implementation is quite similar to OutputStreamWriter. 67 * This leads to some minor duplication, because neither inherits 68 * from the other, and we want to maximize performance. */ 69 70 // Line separator string. 71 private static final char[] line_separator 72 = System.getProperty("line.separator").toCharArray(); 73 74 UnicodeToBytes converter; 75 76 // Work buffer of characters for converter. 77 char[] work = new char[100]; 78 // Work buffer of bytes where we temporarily keep converter output. 79 byte[] work_bytes = new byte[100]; 80 81 /** 82 * This boolean indicates whether or not an error has ever occurred 83 * on this stream. 84 */ 85 private boolean error_occurred = false; 86 87 /** 88 * This is <code>true</code> if auto-flush is enabled, 89 * <code>false</code> otherwise 90 */ 91 private boolean auto_flush; 92 93 /** 94 * This method intializes a new <code>PrintStream</code> object to write 95 * to the specified output sink. 96 * 97 * @param out The <code>OutputStream</code> to write to. 98 */ PrintStream(OutputStream out)99 public PrintStream (OutputStream out) 100 { 101 this (out, false); 102 } 103 104 /** 105 * This method intializes a new <code>PrintStream</code> object to write 106 * to the specified output sink. This constructor also allows "auto-flush" 107 * functionality to be specified where the stream will be flushed after 108 * every <code>print</code> or <code>println</code> call, when the 109 * <code>write</code> methods with array arguments are called, or when a 110 * single new-line character is written. 111 * <p> 112 * 113 * @param out The <code>OutputStream</code> to write to. 114 * @param auto_flush <code>true</code> to flush the stream after every 115 * line, <code>false</code> otherwise 116 */ PrintStream(OutputStream out, boolean auto_flush)117 public PrintStream (OutputStream out, boolean auto_flush) 118 { 119 super (out); 120 121 converter = UnicodeToBytes.getDefaultEncoder(); 122 this.auto_flush = auto_flush; 123 } 124 125 /** 126 * This method initializes a new <code>PrintStream</code> object to write 127 * to the specified output File. Doesn't autoflush. 128 * 129 * @param file The <code>File</code> to write to. 130 * @throws FileNotFoundException if an error occurs while opening the file. 131 * 132 * @since 1.5 133 */ PrintStream(File file)134 public PrintStream (File file) 135 throws FileNotFoundException 136 { 137 this (new FileOutputStream(file), false); 138 } 139 140 /** 141 * This method initializes a new <code>PrintStream</code> object to write 142 * to the specified output File. Doesn't autoflush. 143 * 144 * @param file The <code>File</code> to write to. 145 * @param encoding The name of the character encoding to use for this 146 * object. 147 * @throws FileNotFoundException If an error occurs while opening the file. 148 * @throws UnsupportedEncodingException If the charset specified by 149 * <code>encoding</code> is invalid. 150 * 151 * @since 1.5 152 */ PrintStream(File file, String encoding)153 public PrintStream (File file, String encoding) 154 throws FileNotFoundException,UnsupportedEncodingException 155 { 156 this (new FileOutputStream(file), false, encoding); 157 } 158 159 /** 160 * This method initializes a new <code>PrintStream</code> object to write 161 * to the specified output File. Doesn't autoflush. 162 * 163 * @param fileName The name of the <code>File</code> to write to. 164 * @throws FileNotFoundException if an error occurs while opening the file, 165 * 166 * @since 1.5 167 */ PrintStream(String fileName)168 public PrintStream (String fileName) 169 throws FileNotFoundException 170 { 171 this (new FileOutputStream(new File(fileName)), false); 172 } 173 174 /** 175 * This method initializes a new <code>PrintStream</code> object to write 176 * to the specified output File. Doesn't autoflush. 177 * 178 * @param fileName The name of the <code>File</code> to write to. 179 * @param encoding The name of the character encoding to use for this 180 * object. 181 * @throws FileNotFoundException if an error occurs while opening the file. 182 * @throws UnsupportedEncodingException If the charset specified by 183 * <code>encoding</code> is invalid. 184 * 185 * @since 1.5 186 */ PrintStream(String fileName, String encoding)187 public PrintStream (String fileName, String encoding) 188 throws FileNotFoundException,UnsupportedEncodingException 189 { 190 this (new FileOutputStream(new File(fileName)), false, encoding); 191 } 192 193 /** 194 * This method intializes a new <code>PrintStream</code> object to write 195 * to the specified output sink. This constructor also allows "auto-flush" 196 * functionality to be specified where the stream will be flushed after 197 * every <code>print</code> or <code>println</code> call, when the 198 * <code>write</code> methods with array arguments are called, or when a 199 * single new-line character is written. 200 * <p> 201 * 202 * @param out The <code>OutputStream</code> to write to. 203 * @param auto_flush <code>true</code> to flush the stream after every 204 * line, <code>false</code> otherwise 205 * @param encoding The name of the character encoding to use for this 206 * object. 207 */ PrintStream(OutputStream out, boolean auto_flush, String encoding)208 public PrintStream (OutputStream out, boolean auto_flush, String encoding) 209 throws UnsupportedEncodingException 210 { 211 super (out); 212 213 converter = UnicodeToBytes.getEncoder (encoding); 214 this.auto_flush = auto_flush; 215 } 216 217 /** 218 * This method checks to see if an error has occurred on this stream. Note 219 * that once an error has occurred, this method will continue to report 220 * <code>true</code> forever for this stream. Before checking for an 221 * error condition, this method flushes the stream. 222 * 223 * @return <code>true</code> if an error has occurred, 224 * <code>false</code> otherwise 225 */ checkError()226 public boolean checkError () 227 { 228 flush (); 229 return error_occurred; 230 } 231 232 /** 233 * This method can be called by subclasses to indicate that an error 234 * has occurred and should be reported by <code>checkError</code>. 235 */ setError()236 protected void setError () 237 { 238 error_occurred = true; 239 } 240 241 /** 242 * This method closes this stream and all underlying streams. 243 */ close()244 public void close () 245 { 246 try 247 { 248 converter.setFinished(); 249 writeChars(new char[0], 0, 0); 250 flush(); 251 out.close(); 252 } 253 catch (InterruptedIOException iioe) 254 { 255 Thread.currentThread().interrupt(); 256 } 257 catch (IOException e) 258 { 259 setError (); 260 } 261 } 262 263 /** 264 * This method flushes any buffered bytes to the underlying stream and 265 * then flushes that stream as well. 266 */ flush()267 public void flush () 268 { 269 try 270 { 271 out.flush(); 272 } 273 catch (InterruptedIOException iioe) 274 { 275 Thread.currentThread().interrupt(); 276 } 277 catch (IOException e) 278 { 279 setError (); 280 } 281 } 282 print(String str, boolean println)283 private synchronized void print (String str, boolean println) 284 { 285 try 286 { 287 writeChars(str, 0, str.length()); 288 if (println) 289 writeChars(line_separator, 0, line_separator.length); 290 if (auto_flush) 291 flush(); 292 } 293 catch (InterruptedIOException iioe) 294 { 295 Thread.currentThread().interrupt(); 296 } 297 catch (IOException e) 298 { 299 setError (); 300 } 301 } 302 print(char[] chars, int pos, int len, boolean println)303 private synchronized void print (char[] chars, int pos, int len, 304 boolean println) 305 { 306 try 307 { 308 writeChars(chars, pos, len); 309 if (println) 310 writeChars(line_separator, 0, line_separator.length); 311 if (auto_flush) 312 flush(); 313 } 314 catch (InterruptedIOException iioe) 315 { 316 Thread.currentThread().interrupt(); 317 } 318 catch (IOException e) 319 { 320 setError (); 321 } 322 } 323 writeChars(char[] buf, int offset, int count)324 private void writeChars(char[] buf, int offset, int count) 325 throws IOException 326 { 327 do 328 { 329 converter.setOutput(work_bytes, 0); 330 int converted = converter.write(buf, offset, count); 331 offset += converted; 332 count -= converted; 333 out.write(work_bytes, 0, converter.count); 334 } 335 while (count > 0 || converter.havePendingBytes()); 336 } 337 writeChars(String str, int offset, int count)338 private void writeChars(String str, int offset, int count) 339 throws IOException 340 { 341 do 342 { 343 converter.setOutput(work_bytes, 0); 344 int converted = converter.write(str, offset, count, work); 345 offset += converted; 346 count -= converted; 347 out.write(work_bytes, 0, converter.count); 348 } 349 while (count > 0 || converter.havePendingBytes()); 350 } 351 352 /** 353 * This methods prints a boolean value to the stream. <code>true</code> 354 * values are printed as "true" and <code>false</code> values are printed 355 * as "false". 356 * 357 * @param bool The <code>boolean</code> value to print 358 */ print(boolean bool)359 public void print (boolean bool) 360 { 361 print(String.valueOf(bool), false); 362 } 363 364 /** 365 * This method prints an integer to the stream. The value printed is 366 * determined using the <code>String.valueOf()</code> method. 367 * 368 * @param inum The <code>int</code> value to be printed 369 */ print(int inum)370 public void print (int inum) 371 { 372 print(String.valueOf(inum), false); 373 } 374 375 /** 376 * This method prints a long to the stream. The value printed is 377 * determined using the <code>String.valueOf()</code> method. 378 * 379 * @param lnum The <code>long</code> value to be printed 380 */ print(long lnum)381 public void print (long lnum) 382 { 383 print(String.valueOf(lnum), false); 384 } 385 386 /** 387 * This method prints a float to the stream. The value printed is 388 * determined using the <code>String.valueOf()</code> method. 389 * 390 * @param fnum The <code>float</code> value to be printed 391 */ print(float fnum)392 public void print (float fnum) 393 { 394 print(String.valueOf(fnum), false); 395 } 396 397 /** 398 * This method prints a double to the stream. The value printed is 399 * determined using the <code>String.valueOf()</code> method. 400 * 401 * @param dnum The <code>double</code> value to be printed 402 */ print(double dnum)403 public void print (double dnum) 404 { 405 print(String.valueOf(dnum), false); 406 } 407 408 /** 409 * This method prints an <code>Object</code> to the stream. The actual 410 * value printed is determined by calling the <code>String.valueOf()</code> 411 * method. 412 * 413 * @param obj The <code>Object</code> to print. 414 */ print(Object obj)415 public void print (Object obj) 416 { 417 print(obj == null ? "null" : obj.toString(), false); 418 } 419 420 /** 421 * This method prints a <code>String</code> to the stream. The actual 422 * value printed depends on the system default encoding. 423 * 424 * @param str The <code>String</code> to print. 425 */ print(String str)426 public void print (String str) 427 { 428 print(str == null ? "null" : str, false); 429 } 430 431 /** 432 * This method prints a char to the stream. The actual value printed is 433 * determined by the character encoding in use. 434 * 435 * @param ch The <code>char</code> value to be printed 436 */ print(char ch)437 public synchronized void print (char ch) 438 { 439 work[0] = ch; 440 print(work, 0, 1, false); 441 } 442 443 /** 444 * This method prints an array of characters to the stream. The actual 445 * value printed depends on the system default encoding. 446 * 447 * @param charArray The array of characters to print. 448 */ print(char[] charArray)449 public void print (char[] charArray) 450 { 451 print(charArray, 0, charArray.length, false); 452 } 453 454 /** 455 * This method prints a line separator sequence to the stream. The value 456 * printed is determined by the system property <xmp>line.separator</xmp> 457 * and is not necessarily the Unix '\n' newline character. 458 */ println()459 public void println () 460 { 461 print(line_separator, 0, line_separator.length, false); 462 } 463 464 /** 465 * This methods prints a boolean value to the stream. <code>true</code> 466 * values are printed as "true" and <code>false</code> values are printed 467 * as "false". 468 * <p> 469 * This method prints a line termination sequence after printing the value. 470 * 471 * @param bool The <code>boolean</code> value to print 472 */ println(boolean bool)473 public void println (boolean bool) 474 { 475 print(String.valueOf(bool), true); 476 } 477 478 /** 479 * This method prints an integer to the stream. The value printed is 480 * determined using the <code>String.valueOf()</code> method. 481 * <p> 482 * This method prints a line termination sequence after printing the value. 483 * 484 * @param inum The <code>int</code> value to be printed 485 */ println(int inum)486 public void println (int inum) 487 { 488 print(String.valueOf(inum), true); 489 } 490 491 /** 492 * This method prints a long to the stream. The value printed is 493 * determined using the <code>String.valueOf()</code> method. 494 * <p> 495 * This method prints a line termination sequence after printing the value. 496 * 497 * @param lnum The <code>long</code> value to be printed 498 */ println(long lnum)499 public void println (long lnum) 500 { 501 print(String.valueOf(lnum), true); 502 } 503 504 /** 505 * This method prints a float to the stream. The value printed is 506 * determined using the <code>String.valueOf()</code> method. 507 * <p> 508 * This method prints a line termination sequence after printing the value. 509 * 510 * @param fnum The <code>float</code> value to be printed 511 */ println(float fnum)512 public void println (float fnum) 513 { 514 print(String.valueOf(fnum), true); 515 } 516 517 /** 518 * This method prints a double to the stream. The value printed is 519 * determined using the <code>String.valueOf()</code> method. 520 * <p> 521 * This method prints a line termination sequence after printing the value. 522 * 523 * @param dnum The <code>double</code> value to be printed 524 */ println(double dnum)525 public void println (double dnum) 526 { 527 print(String.valueOf(dnum), true); 528 } 529 530 /** 531 * This method prints an <code>Object</code> to the stream. The actual 532 * value printed is determined by calling the <code>String.valueOf()</code> 533 * method. 534 * <p> 535 * This method prints a line termination sequence after printing the value. 536 * 537 * @param obj The <code>Object</code> to print. 538 */ println(Object obj)539 public void println (Object obj) 540 { 541 print(obj == null ? "null" : obj.toString(), true); 542 } 543 544 /** 545 * This method prints a <code>String</code> to the stream. The actual 546 * value printed depends on the system default encoding. 547 * <p> 548 * This method prints a line termination sequence after printing the value. 549 * 550 * @param str The <code>String</code> to print. 551 */ println(String str)552 public void println (String str) 553 { 554 print (str == null ? "null" : str, true); 555 } 556 557 /** 558 * This method prints a char to the stream. The actual value printed is 559 * determined by the character encoding in use. 560 * <p> 561 * This method prints a line termination sequence after printing the value. 562 * 563 * @param ch The <code>char</code> value to be printed 564 */ println(char ch)565 public synchronized void println (char ch) 566 { 567 work[0] = ch; 568 print(work, 0, 1, true); 569 } 570 571 /** 572 * This method prints an array of characters to the stream. The actual 573 * value printed depends on the system default encoding. 574 * <p> 575 * This method prints a line termination sequence after printing the value. 576 * 577 * @param charArray The array of characters to print. 578 */ println(char[] charArray)579 public void println (char[] charArray) 580 { 581 print(charArray, 0, charArray.length, true); 582 } 583 584 /** 585 * This method writes a byte of data to the stream. If auto-flush is 586 * enabled, printing a newline character will cause the stream to be 587 * flushed after the character is written. 588 * 589 * @param oneByte The byte to be written 590 */ write(int oneByte)591 public void write (int oneByte) 592 { 593 try 594 { 595 out.write (oneByte & 0xff); 596 597 if (auto_flush && (oneByte == '\n')) 598 flush (); 599 } 600 catch (InterruptedIOException iioe) 601 { 602 Thread.currentThread ().interrupt (); 603 } 604 catch (IOException e) 605 { 606 setError (); 607 } 608 } 609 610 /** 611 * This method writes <code>len</code> bytes from the specified array 612 * starting at index <code>offset</code> into the array. 613 * 614 * @param buffer The array of bytes to write 615 * @param offset The index into the array to start writing from 616 * @param len The number of bytes to write 617 */ write(byte[] buffer, int offset, int len)618 public void write (byte[] buffer, int offset, int len) 619 { 620 try 621 { 622 out.write (buffer, offset, len); 623 624 if (auto_flush) 625 flush (); 626 } 627 catch (InterruptedIOException iioe) 628 { 629 Thread.currentThread ().interrupt (); 630 } 631 catch (IOException e) 632 { 633 setError (); 634 } 635 } 636 637 /** @since 1.5 */ append(char c)638 public PrintStream append(char c) 639 { 640 print(c); 641 return this; 642 } 643 644 /** @since 1.5 */ append(CharSequence cs)645 public PrintStream append(CharSequence cs) 646 { 647 print(cs == null ? "null" : cs.toString()); 648 return this; 649 } 650 651 /** @since 1.5 */ append(CharSequence cs, int start, int end)652 public PrintStream append(CharSequence cs, int start, int end) 653 { 654 print(cs == null ? "null" : cs.subSequence(start, end).toString()); 655 return this; 656 } 657 658 /** @since 1.5 */ printf(String format, Object... args)659 public PrintStream printf(String format, Object... args) 660 { 661 return format(format, args); 662 } 663 664 /** @since 1.5 */ printf(Locale locale, String format, Object... args)665 public PrintStream printf(Locale locale, String format, Object... args) 666 { 667 return format(locale, format, args); 668 } 669 670 /** @since 1.5 */ format(String format, Object... args)671 public PrintStream format(String format, Object... args) 672 { 673 return format(Locale.getDefault(), format, args); 674 } 675 676 /** @since 1.5 */ format(Locale locale, String format, Object... args)677 public PrintStream format(Locale locale, String format, Object... args) 678 { 679 Formatter f = new Formatter(this, locale); 680 f.format(format, args); 681 return this; 682 } 683 } // class PrintStream 684 685