1 /* PrintStream.java -- OutputStream for printing output 2 Copyright (C) 1998, 1999, 2001, 2003, 2004, 2005, 2006 3 Free Software Foundation, Inc. 4 5 This file is part of GNU Classpath. 6 7 GNU Classpath is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 2, or (at your option) 10 any later version. 11 12 GNU Classpath is distributed in the hope that it will be useful, but 13 WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with GNU Classpath; see the file COPYING. If not, write to the 19 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 02110-1301 USA. 21 22 Linking this library statically or dynamically with other modules is 23 making a combined work based on this library. Thus, the terms and 24 conditions of the GNU General Public License cover the whole 25 combination. 26 27 As a special exception, the copyright holders of this library give you 28 permission to link this library with independent modules to produce an 29 executable, regardless of the license terms of these independent 30 modules, and to copy and distribute the resulting executable under 31 terms of your choice, provided that you also meet, for each linked 32 independent module, the terms and conditions of the license of that 33 module. An independent module is a module which is not derived from 34 or based on this library. If you modify this library, you may extend 35 this exception to your version of the library, but you are not 36 obligated to do so. If you do not wish to do so, delete this 37 exception statement from your version. */ 38 39 40 package java.io; 41 42 import java.util.Locale; 43 import java.util.Formatter; 44 45 import gnu.classpath.SystemProperties; 46 47 /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3 48 * "The Java Language Specification", ISBN 0-201-63451-1 49 * Status: Believed complete and correct to 1.3 50 */ 51 52 /** 53 * This class prints Java primitive values and object to a stream as 54 * text. None of the methods in this class throw an exception. However, 55 * errors can be detected by calling the <code>checkError()</code> method. 56 * Additionally, this stream can be designated as "autoflush" when 57 * created so that any writes are automatically flushed to the underlying 58 * output sink when the current line is terminated. 59 * <p> 60 * This class converts char's into byte's using the system default encoding. 61 * 62 * @author Aaron M. Renn (arenn@urbanophile.com) 63 * @author Tom Tromey (tromey@cygnus.com) 64 * @author Andrew John Hughes (gnu_andrew@member.fsf.org) 65 */ 66 public class PrintStream extends FilterOutputStream implements Appendable 67 { 68 /* Notice the implementation is quite similar to OutputStreamWriter. 69 * This leads to some minor duplication, because neither inherits 70 * from the other, and we want to maximize performance. */ 71 72 // Line separator string. 73 private static final char[] line_separator 74 = SystemProperties.getProperty("line.separator", "\n").toCharArray(); 75 76 /** 77 * Encoding name 78 */ 79 private final String encoding; 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 final boolean auto_flush; 92 93 /** 94 * This method initializes a new <code>PrintStream</code> object to write 95 * to the specified output File. Doesn't autoflush. 96 * 97 * @param file The <code>File</code> to write to. 98 * @throws FileNotFoundException if an error occurs while opening the file. 99 * 100 * @since 1.5 101 */ PrintStream(File file)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 */ PrintStream(File file, String encoding)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 */ PrintStream(String fileName)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 */ PrintStream(String fileName, String encoding)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 */ PrintStream(OutputStream out)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 */ PrintStream(OutputStream out, boolean auto_flush)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 */ PrintStream(OutputStream out, boolean auto_flush, String encoding)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 */ checkError()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 */ setError()258 protected void setError () 259 { 260 error_occurred = true; 261 } 262 263 /** 264 * This method closes this stream and all underlying streams. 265 */ close()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 */ flush()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 print(String str, boolean println)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 print(char[] chars, int pos, int len, boolean println)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 writeChars(char[] buf, int offset, int count)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 writeChars(String str, int offset, int count)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 */ print(boolean bool)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 */ print(int inum)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 */ print(long lnum)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 */ print(float fnum)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 */ print(double dnum)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 */ print(Object obj)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 */ print(String str)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 */ print(char ch)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 */ print(char[] charArray)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 */ println()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 */ println(boolean bool)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 */ println(int inum)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 */ println(long lnum)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 */ println(float fnum)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 */ println(double dnum)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 */ println(Object obj)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 */ println(String str)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 */ println(char ch)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 */ println(char[] charArray)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 */ write(int oneByte)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 */ write(byte[] buffer, int offset, int len)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 */ append(char c)642 public PrintStream append(char c) 643 { 644 print(c); 645 return this; 646 } 647 648 /** @since 1.5 */ append(CharSequence cs)649 public PrintStream append(CharSequence cs) 650 { 651 print(cs == null ? "null" : cs.toString()); 652 return this; 653 } 654 655 /** @since 1.5 */ append(CharSequence cs, int start, int end)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 */ printf(String format, Object... args)663 public PrintStream printf(String format, Object... args) 664 { 665 return format(format, args); 666 } 667 668 /** @since 1.5 */ printf(Locale locale, String format, Object... args)669 public PrintStream printf(Locale locale, String format, Object... args) 670 { 671 return format(locale, format, args); 672 } 673 674 /** @since 1.5 */ format(String format, Object... args)675 public PrintStream format(String format, Object... args) 676 { 677 return format(Locale.getDefault(), format, args); 678 } 679 680 /** @since 1.5 */ format(Locale locale, String format, Object... args)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 688