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