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