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