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