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