Frames | No Frames |
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