Source for java.io.PrintStream

   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:    */
 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:    */
 185:   public PrintStream (OutputStream out, boolean auto_flush)
 186:   {
 187:     super (out);
 188:     String encoding;
 189:     try {
 190:     encoding = SystemProperties.getProperty("file.encoding");
 191:     } catch (SecurityException e){
 192:     encoding = "ISO8859_1";
 193:     } catch (IllegalArgumentException e){
 194:     encoding = "ISO8859_1";
 195:     } catch (NullPointerException e){
 196:     encoding = "ISO8859_1";
 197:     }
 198:     this.encoding = encoding;
 199:     this.auto_flush = auto_flush;
 200:   }
 201: 
 202:   /**
 203:    * This method initializes a new <code>PrintStream</code> object to write
 204:    * to the specified output sink.  This constructor also allows "auto-flush"
 205:    * functionality to be specified where the stream will be flushed after
 206:    * every <code>print</code> or <code>println</code> call, when the 
 207:    * <code>write</code> methods with array arguments are called, or when a 
 208:    * single new-line character is written.
 209:    * <p>
 210:    *
 211:    * @param out The <code>OutputStream</code> to write to.
 212:    * @param auto_flush <code>true</code> to flush the stream after every 
 213:    * line, <code>false</code> otherwise
 214:    * @param encoding The name of the character encoding to use for this
 215:    * object.
 216:    */
 217:   public PrintStream (OutputStream out, boolean auto_flush, String encoding)
 218:     throws UnsupportedEncodingException
 219:   {
 220:     super (out);
 221: 
 222:     new String(new byte[]{0}, encoding);    // check if encoding is supported
 223:     this.encoding = encoding;
 224:     this.auto_flush = auto_flush;
 225:   }
 226: 
 227:   /**
 228:    * This method checks to see if an error has occurred on this stream.  Note
 229:    * that once an error has occurred, this method will continue to report
 230:    * <code>true</code> forever for this stream.  Before checking for an
 231:    * error condition, this method flushes the stream.
 232:    *
 233:    * @return <code>true</code> if an error has occurred, 
 234:    * <code>false</code> otherwise
 235:    */
 236:   public boolean checkError ()
 237:   {
 238:     flush ();
 239:     return error_occurred;
 240:   }
 241: 
 242:   /**
 243:    * This method can be called by subclasses to indicate that an error
 244:    * has occurred and should be reported by <code>checkError</code>.
 245:    */
 246:   protected void setError ()
 247:   {
 248:     error_occurred = true;
 249:   }
 250: 
 251:   /**
 252:    * This method closes this stream and all underlying streams.
 253:    */
 254:   public void close ()
 255:   {
 256:     try
 257:       {
 258:     flush();
 259:     out.close();
 260:       }
 261:     catch (InterruptedIOException iioe)
 262:       {
 263:     Thread.currentThread().interrupt();
 264:       }
 265:     catch (IOException e)
 266:       {
 267:     setError ();
 268:       }
 269:   }
 270: 
 271:   /**
 272:    * This method flushes any buffered bytes to the underlying stream and
 273:    * then flushes that stream as well.
 274:    */
 275:   public void flush ()
 276:   {
 277:     try
 278:       {
 279:     out.flush();
 280:       }
 281:     catch (InterruptedIOException iioe)
 282:       {
 283:     Thread.currentThread().interrupt();
 284:       }
 285:     catch (IOException e)
 286:       {
 287:     setError ();
 288:       }
 289:   }
 290: 
 291:   private synchronized void print (String str, boolean println)
 292:   {
 293:     try
 294:       {
 295:         writeChars(str, 0, str.length());
 296:     if (println)
 297:       writeChars(line_separator, 0, line_separator.length);
 298:     if (auto_flush)
 299:       flush();
 300:       }
 301:     catch (InterruptedIOException iioe)
 302:       {
 303:     Thread.currentThread().interrupt();
 304:       }
 305:     catch (IOException e)
 306:       {
 307:     setError ();
 308:       }
 309:   }
 310: 
 311:   private synchronized void print (char[] chars, int pos, int len,
 312:                    boolean println)
 313:   {
 314:     try
 315:       {
 316:         writeChars(chars, pos, len);
 317:     if (println)
 318:       writeChars(line_separator, 0, line_separator.length);
 319:     if (auto_flush)
 320:       flush();
 321:       }
 322:     catch (InterruptedIOException iioe)
 323:       {
 324:     Thread.currentThread().interrupt();
 325:       }
 326:     catch (IOException e)
 327:       {
 328:     setError ();
 329:       }
 330:   }
 331: 
 332:   private void writeChars(char[] buf, int offset, int count)
 333:     throws IOException
 334:   {
 335:       byte[] bytes = (new String(buf, offset, count)).getBytes(encoding);
 336:       out.write(bytes, 0, bytes.length);
 337:   }
 338: 
 339:   private void writeChars(String str, int offset, int count)
 340:     throws IOException
 341:   {
 342:       byte[] bytes = str.substring(offset, offset+count).getBytes(encoding);
 343:       out.write(bytes, 0, bytes.length);
 344:   }
 345: 
 346:   /**
 347:    * This methods prints a boolean value to the stream.  <code>true</code>
 348:    * values are printed as "true" and <code>false</code> values are printed
 349:    * as "false".
 350:    *
 351:    * @param bool The <code>boolean</code> value to print
 352:    */
 353:   public void print (boolean bool)
 354:   {
 355:     print(String.valueOf(bool), false);
 356:   }
 357: 
 358:   /**
 359:    * This method prints an integer to the stream.  The value printed is
 360:    * determined using the <code>String.valueOf()</code> method.
 361:    *
 362:    * @param inum The <code>int</code> value to be printed
 363:    */
 364:   public void print (int inum)
 365:   {
 366:     print(String.valueOf(inum), false);
 367:   }
 368: 
 369:   /**
 370:    * This method prints a long to the stream.  The value printed is
 371:    * determined using the <code>String.valueOf()</code> method.
 372:    *
 373:    * @param lnum The <code>long</code> value to be printed
 374:    */
 375:   public void print (long lnum)
 376:   {
 377:     print(String.valueOf(lnum), false);
 378:   }
 379: 
 380:   /**
 381:    * This method prints a float to the stream.  The value printed is
 382:    * determined using the <code>String.valueOf()</code> method.
 383:    *
 384:    * @param fnum The <code>float</code> value to be printed
 385:    */
 386:   public void print (float fnum)
 387:   {
 388:     print(String.valueOf(fnum), false);
 389:   }
 390: 
 391:   /**
 392:    * This method prints a double to the stream.  The value printed is
 393:    * determined using the <code>String.valueOf()</code> method.
 394:    *
 395:    * @param dnum The <code>double</code> value to be printed
 396:    */
 397:   public void print (double dnum)
 398:   {
 399:     print(String.valueOf(dnum), false);
 400:   }
 401: 
 402:   /**
 403:    * This method prints an <code>Object</code> to the stream.  The actual
 404:    * value printed is determined by calling the <code>String.valueOf()</code>
 405:    * method.
 406:    *
 407:    * @param obj The <code>Object</code> to print.
 408:    */
 409:   public void print (Object obj)
 410:   {
 411:     print(obj == null ? "null" : obj.toString(), false);
 412:   }
 413: 
 414:   /**
 415:    * This method prints a <code>String</code> to the stream.  The actual
 416:    * value printed depends on the system default encoding.
 417:    *
 418:    * @param str The <code>String</code> to print.
 419:    */
 420:   public void print (String str)
 421:   {
 422:     print(str == null ? "null" : str, false);
 423:   }
 424: 
 425:   /**
 426:    * This method prints a char to the stream.  The actual value printed is
 427:    * determined by the character encoding in use.
 428:    *
 429:    * @param ch The <code>char</code> value to be printed
 430:    */
 431:   public synchronized void print (char ch)
 432:   {
 433:     print(new char[]{ch}, 0, 1, false);
 434:   }
 435: 
 436:   /**
 437:    * This method prints an array of characters to the stream.  The actual
 438:    * value printed depends on the system default encoding.
 439:    *
 440:    * @param charArray The array of characters to print.
 441:    */
 442:   public void print (char[] charArray)
 443:   {
 444:     print(charArray, 0, charArray.length, false);
 445:   }
 446: 
 447:   /**
 448:    * This method prints a line separator sequence to the stream.  The value
 449:    * printed is determined by the system property <xmp>line.separator</xmp>
 450:    * and is not necessarily the Unix '\n' newline character.
 451:    */
 452:   public void println ()
 453:   {
 454:     print(line_separator, 0, line_separator.length, false);
 455:   }
 456: 
 457:   /**
 458:    * This methods prints a boolean value to the stream.  <code>true</code>
 459:    * values are printed as "true" and <code>false</code> values are printed
 460:    * as "false".
 461:    * <p>
 462:    * This method prints a line termination sequence after printing the value.
 463:    *
 464:    * @param bool The <code>boolean</code> value to print
 465:    */
 466:   public void println (boolean bool)
 467:   {
 468:     print(String.valueOf(bool), true);
 469:   }
 470: 
 471:   /**
 472:    * This method prints an integer to the stream.  The value printed is
 473:    * determined using the <code>String.valueOf()</code> method.
 474:    * <p>
 475:    * This method prints a line termination sequence after printing the value.
 476:    *
 477:    * @param inum The <code>int</code> value to be printed
 478:    */
 479:   public void println (int inum)
 480:   {
 481:     print(String.valueOf(inum), true);
 482:   }
 483: 
 484:   /**
 485:    * This method prints a long to the stream.  The value printed is
 486:    * determined using the <code>String.valueOf()</code> method.
 487:    * <p>
 488:    * This method prints a line termination sequence after printing the value.
 489:    *
 490:    * @param lnum The <code>long</code> value to be printed
 491:    */
 492:   public void println (long lnum)
 493:   {
 494:     print(String.valueOf(lnum), true);
 495:   }
 496: 
 497:   /**
 498:    * This method prints a float to the stream.  The value printed is
 499:    * determined using the <code>String.valueOf()</code> method.
 500:    * <p>
 501:    * This method prints a line termination sequence after printing the value.
 502:    *
 503:    * @param fnum The <code>float</code> value to be printed
 504:    */
 505:   public void println (float fnum)
 506:   {
 507:     print(String.valueOf(fnum), true);
 508:   }
 509: 
 510:   /**
 511:    * This method prints a double to the stream.  The value printed is
 512:    * determined using the <code>String.valueOf()</code> method.
 513:    * <p>
 514:    * This method prints a line termination sequence after printing the value.
 515:    *
 516:    * @param dnum The <code>double</code> value to be printed
 517:    */
 518:   public void println (double dnum)
 519:   {
 520:     print(String.valueOf(dnum), true);
 521:   }
 522: 
 523:   /**
 524:    * This method prints an <code>Object</code> to the stream.  The actual
 525:    * value printed is determined by calling the <code>String.valueOf()</code>
 526:    * method.
 527:    * <p>
 528:    * This method prints a line termination sequence after printing the value.
 529:    *
 530:    * @param obj The <code>Object</code> to print.
 531:    */
 532:   public void println (Object obj)
 533:   {
 534:     print(obj == null ? "null" : obj.toString(), true);
 535:   }
 536: 
 537:   /**
 538:    * This method prints a <code>String</code> to the stream.  The actual
 539:    * value printed depends on the system default encoding.
 540:    * <p>
 541:    * This method prints a line termination sequence after printing the value.
 542:    *
 543:    * @param str The <code>String</code> to print.
 544:    */
 545:   public void println (String str)
 546:   {
 547:     print (str == null ? "null" : str, true);
 548:   }
 549: 
 550:   /**
 551:    * This method prints a char to the stream.  The actual value printed is
 552:    * determined by the character encoding in use.
 553:    * <p>
 554:    * This method prints a line termination sequence after printing the value.
 555:    *
 556:    * @param ch The <code>char</code> value to be printed
 557:    */
 558:   public synchronized void println (char ch)
 559:   {
 560:     print(new char[]{ch}, 0, 1, true);
 561:   }
 562: 
 563:   /**
 564:    * This method prints an array of characters to the stream.  The actual
 565:    * value printed depends on the system default encoding.
 566:    * <p>
 567:    * This method prints a line termination sequence after printing the value.
 568:    *
 569:    * @param charArray The array of characters to print.
 570:    */
 571:   public void println (char[] charArray)
 572:   {
 573:     print(charArray, 0, charArray.length, true);
 574:   }
 575: 
 576:   /**
 577:    * This method writes a byte of data to the stream.  If auto-flush is
 578:    * enabled, printing a newline character will cause the stream to be
 579:    * flushed after the character is written.
 580:    * 
 581:    * @param oneByte The byte to be written
 582:    */
 583:   public void write (int oneByte)
 584:   {
 585:     try
 586:       {
 587:         out.write (oneByte & 0xff);
 588:         
 589:         if (auto_flush && (oneByte == '\n'))
 590:           flush ();
 591:       }
 592:     catch (InterruptedIOException iioe)
 593:       {
 594:     Thread.currentThread ().interrupt ();
 595:       }
 596:     catch (IOException e)
 597:       {
 598:         setError ();
 599:       }
 600:   }
 601: 
 602:   /**
 603:    * This method writes <code>len</code> bytes from the specified array
 604:    * starting at index <code>offset</code> into the array.
 605:    *
 606:    * @param buffer The array of bytes to write
 607:    * @param offset The index into the array to start writing from
 608:    * @param len The number of bytes to write
 609:    */
 610:   public void write (byte[] buffer, int offset, int len)
 611:   {
 612:     try
 613:       {
 614:         out.write (buffer, offset, len);
 615:         
 616:         if (auto_flush)
 617:           flush ();
 618:       }
 619:     catch (InterruptedIOException iioe)
 620:       {
 621:     Thread.currentThread ().interrupt ();
 622:       }
 623:     catch (IOException e)
 624:       {
 625:         setError ();
 626:       }
 627:   }
 628: 
 629:   /** @since 1.5 */
 630:   public PrintStream append(char c)
 631:   {
 632:     print(c);
 633:     return this;
 634:   }
 635: 
 636:   /** @since 1.5 */
 637:   public PrintStream append(CharSequence cs)
 638:   {
 639:     print(cs == null ? "null" : cs.toString());
 640:     return this;
 641:   }
 642: 
 643:   /** @since 1.5 */
 644:   public PrintStream append(CharSequence cs, int start, int end)
 645:   {
 646:     print(cs == null ? "null" : cs.subSequence(start, end).toString());
 647:     return this;
 648:   }
 649: 
 650:   /** @since 1.5 */
 651:   public PrintStream printf(String format, Object... args)
 652:   {
 653:     return format(format, args);
 654:   }
 655: 
 656:   /** @since 1.5 */
 657:   public PrintStream printf(Locale locale, String format, Object... args)
 658:   {
 659:     return format(locale, format, args);
 660:   }
 661: 
 662:   /** @since 1.5 */
 663:   public PrintStream format(String format, Object... args)
 664:   {
 665:     return format(Locale.getDefault(), format, args);
 666:   }
 667: 
 668:   /** @since 1.5 */
 669:   public PrintStream format(Locale locale, String format, Object... args)
 670:   {
 671:     Formatter f = new Formatter(this, locale);
 672:     f.format(format, args);
 673:     return this;
 674:   }
 675: } // class PrintStream