Source for java.io.PrintStream

   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:    */
  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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 236:   protected void setError ()
 237:   {
 238:     error_occurred = true;
 239:   }
 240: 
 241:   /**
 242:    * This method closes this stream and all underlying streams.
 243:    */
 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:    */
 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: 
 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: 
 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: 
 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: 
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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 */
 638:   public PrintStream append(char c)
 639:   {
 640:     print(c);
 641:     return this;
 642:   }
 643: 
 644:   /** @since 1.5 */
 645:   public PrintStream append(CharSequence cs)
 646:   {
 647:     print(cs == null ? "null" : cs.toString());
 648:     return this;
 649:   }
 650: 
 651:   /** @since 1.5 */
 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 */
 659:   public PrintStream printf(String format, Object... args)
 660:   {
 661:     return format(format, args);
 662:   }
 663: 
 664:   /** @since 1.5 */
 665:   public PrintStream printf(Locale locale, String format, Object... args)
 666:   {
 667:     return format(locale, format, args);
 668:   }
 669: 
 670:   /** @since 1.5 */
 671:   public PrintStream format(String format, Object... args)
 672:   {
 673:     return format(Locale.getDefault(), format, args);
 674:   }
 675: 
 676:   /** @since 1.5 */
 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