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