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 gnu.classpath.SystemProperties;
  43: 
  44: /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
  45:  * "The Java Language Specification", ISBN 0-201-63451-1
  46:  * Status:  Believed complete and correct to 1.3
  47:  */
  48: 
  49: /**
  50:  * This class prints Java primitive values and object to a stream as
  51:  * text.  None of the methods in this class throw an exception.  However,
  52:  * errors can be detected by calling the <code>checkError()</code> method.
  53:  * Additionally, this stream can be designated as "autoflush" when 
  54:  * created so that any writes are automatically flushed to the underlying
  55:  * output sink when the current line is terminated.
  56:  * <p>
  57:  * This class converts char's into byte's using the system default encoding.
  58:  *
  59:  * @author Aaron M. Renn (arenn@urbanophile.com)
  60:  * @author Tom Tromey (tromey@cygnus.com)
  61:  */
  62: public class PrintStream extends FilterOutputStream
  63: {
  64:   /* Notice the implementation is quite similar to OutputStreamWriter.
  65:    * This leads to some minor duplication, because neither inherits
  66:    * from the other, and we want to maximize performance. */
  67: 
  68:   // Line separator string.
  69:   private static final char[] line_separator
  70:     = SystemProperties.getProperty("line.separator").toCharArray();
  71: 
  72:   /**
  73:    *  Encoding name
  74:    */
  75:   private String encoding;
  76: 
  77:   /**
  78:    * This boolean indicates whether or not an error has ever occurred
  79:    * on this stream.
  80:    */
  81:   private boolean error_occurred = false;
  82: 
  83:   /**
  84:    * This is <code>true</code> if auto-flush is enabled, 
  85:    * <code>false</code> otherwise
  86:    */
  87:   private boolean auto_flush;
  88: 
  89:   /**
  90:    * This method initializes a new <code>PrintStream</code> object to write
  91:    * to the specified output File. Doesn't autoflush.
  92:    *
  93:    * @param file The <code>File</code> to write to.
  94:    * @throws FileNotFoundException if an error occurs while opening the file.
  95:    *
  96:    * @since 1.5
  97:    */
  98:   public PrintStream (File file)
  99:     throws FileNotFoundException
 100:   {
 101:     this (new FileOutputStream(file), false);
 102:   }
 103: 
 104:   /**
 105:    * This method initializes a new <code>PrintStream</code> object to write
 106:    * to the specified output File. Doesn't autoflush.
 107:    *
 108:    * @param file The <code>File</code> to write to.
 109:    * @param encoding The name of the character encoding to use for this
 110:    * object.
 111:    * @throws FileNotFoundException If an error occurs while opening the file.
 112:    * @throws UnsupportedEncodingException If the charset specified by
 113:    * <code>encoding</code> is invalid.
 114:    *
 115:    * @since 1.5
 116:    */
 117:   public PrintStream (File file, String encoding)
 118:     throws FileNotFoundException,UnsupportedEncodingException
 119:   {
 120:     this (new FileOutputStream(file), false, encoding);
 121:   }
 122: 
 123:   /**
 124:    * This method initializes a new <code>PrintStream</code> object to write
 125:    * to the specified output File. Doesn't autoflush.
 126:    *
 127:    * @param fileName The name of the <code>File</code> to write to.
 128:    * @throws FileNotFoundException if an error occurs while opening the file,
 129:    *
 130:    * @since 1.5
 131:    */
 132:   public PrintStream (String fileName)
 133:     throws FileNotFoundException
 134:   {
 135:     this (new FileOutputStream(new File(fileName)), false);
 136:   }
 137: 
 138:   /**
 139:    * This method initializes a new <code>PrintStream</code> object to write
 140:    * to the specified output File. Doesn't autoflush.
 141:    *
 142:    * @param fileName The name of the <code>File</code> to write to.
 143:    * @param encoding The name of the character encoding to use for this
 144:    * object.
 145:    * @throws FileNotFoundException if an error occurs while opening the file.
 146:    * @throws UnsupportedEncodingException If the charset specified by
 147:    * <code>encoding</code> is invalid.
 148:    *
 149:    * @since 1.5
 150:    */
 151:   public PrintStream (String fileName, String encoding)
 152:       throws FileNotFoundException,UnsupportedEncodingException
 153:   {
 154:     this (new FileOutputStream(new File(fileName)), false, encoding);
 155:   }
 156: 
 157:   /**
 158:    * This method initializes a new <code>PrintStream</code> object to write
 159:    * to the specified output sink. Doesn't autoflush.
 160:    *
 161:    * @param out The <code>OutputStream</code> to write to.
 162:    */
 163:   public PrintStream (OutputStream out)
 164:   {
 165:     this (out, false);
 166:   }
 167: 
 168:   /**
 169:    * This method initializes a new <code>PrintStream</code> object to write
 170:    * to the specified output sink.  This constructor also allows "auto-flush"
 171:    * functionality to be specified where the stream will be flushed after
 172:    * every <code>print</code> or <code>println</code> call, when the 
 173:    * <code>write</code> methods with array arguments are called, or when a 
 174:    * single new-line character is written.
 175:    * <p>
 176:    *
 177:    * @param out The <code>OutputStream</code> to write to.
 178:    * @param auto_flush <code>true</code> to flush the stream after every 
 179:    * line, <code>false</code> otherwise
 180:    */
 181:   public PrintStream (OutputStream out, boolean auto_flush)
 182:   {
 183:     super (out);
 184: 
 185:     try {
 186:     this.encoding = SystemProperties.getProperty("file.encoding");
 187:     } catch (SecurityException e){
 188:     this.encoding = "ISO8859_1";
 189:     } catch (IllegalArgumentException e){
 190:     this.encoding = "ISO8859_1";
 191:     } catch (NullPointerException e){
 192:     this.encoding = "ISO8859_1";
 193:     }
 194:     this.auto_flush = auto_flush;
 195:   }
 196: 
 197:   /**
 198:    * This method initializes a new <code>PrintStream</code> object to write
 199:    * to the specified output sink.  This constructor also allows "auto-flush"
 200:    * functionality to be specified where the stream will be flushed after
 201:    * every <code>print</code> or <code>println</code> call, when the 
 202:    * <code>write</code> methods with array arguments are called, or when a 
 203:    * single new-line character is written.
 204:    * <p>
 205:    *
 206:    * @param out The <code>OutputStream</code> to write to.
 207:    * @param auto_flush <code>true</code> to flush the stream after every 
 208:    * line, <code>false</code> otherwise
 209:    * @param encoding The name of the character encoding to use for this
 210:    * object.
 211:    */
 212:   public PrintStream (OutputStream out, boolean auto_flush, String encoding)
 213:     throws UnsupportedEncodingException
 214:   {
 215:     super (out);
 216: 
 217:     new String(new byte[]{0}, encoding);    // check if encoding is supported
 218:     this.encoding = encoding;
 219:     this.auto_flush = auto_flush;
 220:   }
 221: 
 222:   /**
 223:    * This method checks to see if an error has occurred on this stream.  Note
 224:    * that once an error has occurred, this method will continue to report
 225:    * <code>true</code> forever for this stream.  Before checking for an
 226:    * error condition, this method flushes the stream.
 227:    *
 228:    * @return <code>true</code> if an error has occurred, 
 229:    * <code>false</code> otherwise
 230:    */
 231:   public boolean checkError ()
 232:   {
 233:     flush ();
 234:     return error_occurred;
 235:   }
 236: 
 237:   /**
 238:    * This method can be called by subclasses to indicate that an error
 239:    * has occurred and should be reported by <code>checkError</code>.
 240:    */
 241:   protected void setError ()
 242:   {
 243:     error_occurred = true;
 244:   }
 245: 
 246:   /**
 247:    * This method closes this stream and all underlying streams.
 248:    */
 249:   public void close ()
 250:   {
 251:     try
 252:       {
 253:     flush();
 254:     out.close();
 255:       }
 256:     catch (InterruptedIOException iioe)
 257:       {
 258:     Thread.currentThread().interrupt();
 259:       }
 260:     catch (IOException e)
 261:       {
 262:     setError ();
 263:       }
 264:   }
 265: 
 266:   /**
 267:    * This method flushes any buffered bytes to the underlying stream and
 268:    * then flushes that stream as well.
 269:    */
 270:   public void flush ()
 271:   {
 272:     try
 273:       {
 274:     out.flush();
 275:       }
 276:     catch (InterruptedIOException iioe)
 277:       {
 278:     Thread.currentThread().interrupt();
 279:       }
 280:     catch (IOException e)
 281:       {
 282:     setError ();
 283:       }
 284:   }
 285: 
 286:   private synchronized void print (String str, boolean println)
 287:   {
 288:     try
 289:       {
 290:         writeChars(str, 0, str.length());
 291:     if (println)
 292:       writeChars(line_separator, 0, line_separator.length);
 293:     if (auto_flush)
 294:       flush();
 295:       }
 296:     catch (InterruptedIOException iioe)
 297:       {
 298:     Thread.currentThread().interrupt();
 299:       }
 300:     catch (IOException e)
 301:       {
 302:     setError ();
 303:       }
 304:   }
 305: 
 306:   private synchronized void print (char[] chars, int pos, int len,
 307:                    boolean println)
 308:   {
 309:     try
 310:       {
 311:         writeChars(chars, pos, len);
 312:     if (println)
 313:       writeChars(line_separator, 0, line_separator.length);
 314:     if (auto_flush)
 315:       flush();
 316:       }
 317:     catch (InterruptedIOException iioe)
 318:       {
 319:     Thread.currentThread().interrupt();
 320:       }
 321:     catch (IOException e)
 322:       {
 323:     setError ();
 324:       }
 325:   }
 326: 
 327:   private void writeChars(char[] buf, int offset, int count)
 328:     throws IOException
 329:   {
 330:       byte[] bytes = (new String(buf, offset, count)).getBytes(encoding);
 331:       out.write(bytes, 0, bytes.length);
 332:   }
 333: 
 334:   private void writeChars(String str, int offset, int count)
 335:     throws IOException
 336:   {
 337:       byte[] bytes = str.substring(offset, offset+count).getBytes(encoding);
 338:       out.write(bytes, 0, bytes.length);
 339:   }
 340: 
 341:   /**
 342:    * This methods prints a boolean value to the stream.  <code>true</code>
 343:    * values are printed as "true" and <code>false</code> values are printed
 344:    * as "false".
 345:    *
 346:    * @param bool The <code>boolean</code> value to print
 347:    */
 348:   public void print (boolean bool)
 349:   {
 350:     print(String.valueOf(bool), false);
 351:   }
 352: 
 353:   /**
 354:    * This method prints an integer to the stream.  The value printed is
 355:    * determined using the <code>String.valueOf()</code> method.
 356:    *
 357:    * @param inum The <code>int</code> value to be printed
 358:    */
 359:   public void print (int inum)
 360:   {
 361:     print(String.valueOf(inum), false);
 362:   }
 363: 
 364:   /**
 365:    * This method prints a long to the stream.  The value printed is
 366:    * determined using the <code>String.valueOf()</code> method.
 367:    *
 368:    * @param lnum The <code>long</code> value to be printed
 369:    */
 370:   public void print (long lnum)
 371:   {
 372:     print(String.valueOf(lnum), false);
 373:   }
 374: 
 375:   /**
 376:    * This method prints a float to the stream.  The value printed is
 377:    * determined using the <code>String.valueOf()</code> method.
 378:    *
 379:    * @param fnum The <code>float</code> value to be printed
 380:    */
 381:   public void print (float fnum)
 382:   {
 383:     print(String.valueOf(fnum), false);
 384:   }
 385: 
 386:   /**
 387:    * This method prints a double to the stream.  The value printed is
 388:    * determined using the <code>String.valueOf()</code> method.
 389:    *
 390:    * @param dnum The <code>double</code> value to be printed
 391:    */
 392:   public void print (double dnum)
 393:   {
 394:     print(String.valueOf(dnum), false);
 395:   }
 396: 
 397:   /**
 398:    * This method prints an <code>Object</code> to the stream.  The actual
 399:    * value printed is determined by calling the <code>String.valueOf()</code>
 400:    * method.
 401:    *
 402:    * @param obj The <code>Object</code> to print.
 403:    */
 404:   public void print (Object obj)
 405:   {
 406:     print(obj == null ? "null" : obj.toString(), false);
 407:   }
 408: 
 409:   /**
 410:    * This method prints a <code>String</code> to the stream.  The actual
 411:    * value printed depends on the system default encoding.
 412:    *
 413:    * @param str The <code>String</code> to print.
 414:    */
 415:   public void print (String str)
 416:   {
 417:     print(str == null ? "null" : str, false);
 418:   }
 419: 
 420:   /**
 421:    * This method prints a char to the stream.  The actual value printed is
 422:    * determined by the character encoding in use.
 423:    *
 424:    * @param ch The <code>char</code> value to be printed
 425:    */
 426:   public synchronized void print (char ch)
 427:   {
 428:     print(new char[]{ch}, 0, 1, false);
 429:   }
 430: 
 431:   /**
 432:    * This method prints an array of characters to the stream.  The actual
 433:    * value printed depends on the system default encoding.
 434:    *
 435:    * @param charArray The array of characters to print.
 436:    */
 437:   public void print (char[] charArray)
 438:   {
 439:     print(charArray, 0, charArray.length, false);
 440:   }
 441: 
 442:   /**
 443:    * This method prints a line separator sequence to the stream.  The value
 444:    * printed is determined by the system property <xmp>line.separator</xmp>
 445:    * and is not necessarily the Unix '\n' newline character.
 446:    */
 447:   public void println ()
 448:   {
 449:     print(line_separator, 0, line_separator.length, false);
 450:   }
 451: 
 452:   /**
 453:    * This methods prints a boolean value to the stream.  <code>true</code>
 454:    * values are printed as "true" and <code>false</code> values are printed
 455:    * as "false".
 456:    * <p>
 457:    * This method prints a line termination sequence after printing the value.
 458:    *
 459:    * @param bool The <code>boolean</code> value to print
 460:    */
 461:   public void println (boolean bool)
 462:   {
 463:     print(String.valueOf(bool), true);
 464:   }
 465: 
 466:   /**
 467:    * This method prints an integer to the stream.  The value printed is
 468:    * determined using the <code>String.valueOf()</code> method.
 469:    * <p>
 470:    * This method prints a line termination sequence after printing the value.
 471:    *
 472:    * @param inum The <code>int</code> value to be printed
 473:    */
 474:   public void println (int inum)
 475:   {
 476:     print(String.valueOf(inum), true);
 477:   }
 478: 
 479:   /**
 480:    * This method prints a long to the stream.  The value printed is
 481:    * determined using the <code>String.valueOf()</code> method.
 482:    * <p>
 483:    * This method prints a line termination sequence after printing the value.
 484:    *
 485:    * @param lnum The <code>long</code> value to be printed
 486:    */
 487:   public void println (long lnum)
 488:   {
 489:     print(String.valueOf(lnum), true);
 490:   }
 491: 
 492:   /**
 493:    * This method prints a float to the stream.  The value printed is
 494:    * determined using the <code>String.valueOf()</code> method.
 495:    * <p>
 496:    * This method prints a line termination sequence after printing the value.
 497:    *
 498:    * @param fnum The <code>float</code> value to be printed
 499:    */
 500:   public void println (float fnum)
 501:   {
 502:     print(String.valueOf(fnum), true);
 503:   }
 504: 
 505:   /**
 506:    * This method prints a double to the stream.  The value printed is
 507:    * determined using the <code>String.valueOf()</code> method.
 508:    * <p>
 509:    * This method prints a line termination sequence after printing the value.
 510:    *
 511:    * @param dnum The <code>double</code> value to be printed
 512:    */
 513:   public void println (double dnum)
 514:   {
 515:     print(String.valueOf(dnum), true);
 516:   }
 517: 
 518:   /**
 519:    * This method prints an <code>Object</code> to the stream.  The actual
 520:    * value printed is determined by calling the <code>String.valueOf()</code>
 521:    * method.
 522:    * <p>
 523:    * This method prints a line termination sequence after printing the value.
 524:    *
 525:    * @param obj The <code>Object</code> to print.
 526:    */
 527:   public void println (Object obj)
 528:   {
 529:     print(obj == null ? "null" : obj.toString(), true);
 530:   }
 531: 
 532:   /**
 533:    * This method prints a <code>String</code> to the stream.  The actual
 534:    * value printed depends on the system default encoding.
 535:    * <p>
 536:    * This method prints a line termination sequence after printing the value.
 537:    *
 538:    * @param str The <code>String</code> to print.
 539:    */
 540:   public void println (String str)
 541:   {
 542:     print (str == null ? "null" : str, true);
 543:   }
 544: 
 545:   /**
 546:    * This method prints a char to the stream.  The actual value printed is
 547:    * determined by the character encoding in use.
 548:    * <p>
 549:    * This method prints a line termination sequence after printing the value.
 550:    *
 551:    * @param ch The <code>char</code> value to be printed
 552:    */
 553:   public synchronized void println (char ch)
 554:   {
 555:     print(new char[]{ch}, 0, 1, true);
 556:   }
 557: 
 558:   /**
 559:    * This method prints an array of characters to the stream.  The actual
 560:    * value printed depends on the system default encoding.
 561:    * <p>
 562:    * This method prints a line termination sequence after printing the value.
 563:    *
 564:    * @param charArray The array of characters to print.
 565:    */
 566:   public void println (char[] charArray)
 567:   {
 568:     print(charArray, 0, charArray.length, true);
 569:   }
 570: 
 571:   /**
 572:    * This method writes a byte of data to the stream.  If auto-flush is
 573:    * enabled, printing a newline character will cause the stream to be
 574:    * flushed after the character is written.
 575:    * 
 576:    * @param oneByte The byte to be written
 577:    */
 578:   public void write (int oneByte)
 579:   {
 580:     try
 581:       {
 582:         out.write (oneByte & 0xff);
 583:         
 584:         if (auto_flush && (oneByte == '\n'))
 585:           flush ();
 586:       }
 587:     catch (InterruptedIOException iioe)
 588:       {
 589:     Thread.currentThread ().interrupt ();
 590:       }
 591:     catch (IOException e)
 592:       {
 593:         setError ();
 594:       }
 595:   }
 596: 
 597:   /**
 598:    * This method writes <code>len</code> bytes from the specified array
 599:    * starting at index <code>offset</code> into the array.
 600:    *
 601:    * @param buffer The array of bytes to write
 602:    * @param offset The index into the array to start writing from
 603:    * @param len The number of bytes to write
 604:    */
 605:   public void write (byte[] buffer, int offset, int len)
 606:   {
 607:     try
 608:       {
 609:         out.write (buffer, offset, len);
 610:         
 611:         if (auto_flush)
 612:           flush ();
 613:       }
 614:     catch (InterruptedIOException iioe)
 615:       {
 616:     Thread.currentThread ().interrupt ();
 617:       }
 618:     catch (IOException e)
 619:       {
 620:         setError ();
 621:       }
 622:   }
 623: } // class PrintStream