1 /*
   2  * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.io;
  27 
  28 import java.util.Formatter;
  29 import java.util.Locale;
  30 import java.nio.charset.Charset;
  31 import java.nio.charset.IllegalCharsetNameException;
  32 import java.nio.charset.UnsupportedCharsetException;
  33 
  34 /**
  35  * A {@code PrintStream} adds functionality to another output stream,
  36  * namely the ability to print representations of various data values
  37  * conveniently.  Two other features are provided as well.  Unlike other output
  38  * streams, a {@code PrintStream} never throws an
  39  * {@code IOException}; instead, exceptional situations merely set an
  40  * internal flag that can be tested via the {@code checkError} method.
  41  * Optionally, a {@code PrintStream} can be created so as to flush
  42  * automatically; this means that the {@code flush} method is
  43  * automatically invoked after a byte array is written, one of the
  44  * {@code println} methods is invoked, or a newline character or byte
  45  * ({@code '\n'}) is written.
  46  *
  47  * <p> All characters printed by a {@code PrintStream} are converted into
  48  * bytes using the given encoding or charset, or the platform's default
  49  * character encoding if not specified.
  50  * The {@link PrintWriter} class should be used in situations that require
  51  * writing characters rather than bytes.
  52  *
  53  * <p> This class always replaces malformed and unmappable character sequences with
  54  * the charset's default replacement string.
  55  * The {@linkplain java.nio.charset.CharsetEncoder} class should be used when more
  56  * control over the encoding process is required.
  57  *
  58  * @author     Frank Yellin
  59  * @author     Mark Reinhold
  60  * @since      1.0
  61  */
  62 
  63 public class PrintStream extends FilterOutputStream
  64     implements Appendable, Closeable
  65 {
  66 
  67     private final boolean autoFlush;
  68     private boolean trouble = false;
  69     private Formatter formatter;
  70 
  71     /**
  72      * Track both the text- and character-output streams, so that their buffers
  73      * can be flushed without flushing the entire stream.
  74      */
  75     private BufferedWriter textOut;
  76     private OutputStreamWriter charOut;
  77 
  78     /**
  79      * requireNonNull is explicitly declared here so as not to create an extra
  80      * dependency on java.util.Objects.requireNonNull. PrintStream is loaded
  81      * early during system initialization.
  82      */
  83     private static <T> T requireNonNull(T obj, String message) {
  84         if (obj == null)
  85             throw new NullPointerException(message);
  86         return obj;
  87     }
  88 
  89     /**
  90      * Returns a charset object for the given charset name.
  91      * @throws NullPointerException          is csn is null
  92      * @throws UnsupportedEncodingException  if the charset is not supported
  93      */
  94     private static Charset toCharset(String csn)
  95         throws UnsupportedEncodingException
  96     {
  97         requireNonNull(csn, "charsetName");
  98         try {
  99             return Charset.forName(csn);
 100         } catch (IllegalCharsetNameException|UnsupportedCharsetException unused) {
 101             // UnsupportedEncodingException should be thrown
 102             throw new UnsupportedEncodingException(csn);
 103         }
 104     }
 105 
 106     /* Private constructors */
 107     private PrintStream(boolean autoFlush, OutputStream out) {
 108         super(out);
 109         this.autoFlush = autoFlush;
 110         this.charOut = new OutputStreamWriter(this);
 111         this.textOut = new BufferedWriter(charOut);
 112     }
 113 
 114     /* Variant of the private constructor so that the given charset name
 115      * can be verified before evaluating the OutputStream argument. Used
 116      * by constructors creating a FileOutputStream that also take a
 117      * charset name.
 118      */
 119     private PrintStream(boolean autoFlush, Charset charset, OutputStream out) {
 120         this(out, autoFlush, charset);
 121     }
 122 
 123     /**
 124      * Creates a new print stream, without automatic line flushing, with the
 125      * specified OutputStream. Characters written to the stream are converted
 126      * to bytes using the platform's default character encoding.
 127      *
 128      * @param  out        The output stream to which values and objects will be
 129      *                    printed
 130      *
 131      * @see java.io.PrintWriter#PrintWriter(java.io.OutputStream)
 132      */
 133     public PrintStream(OutputStream out) {
 134         this(out, false);
 135     }
 136 
 137     /**
 138      * Creates a new print stream, with the specified OutputStream and line
 139      * flushing. Characters written to the stream are converted to bytes using
 140      * the platform's default character encoding.
 141      *
 142      * @param  out        The output stream to which values and objects will be
 143      *                    printed
 144      * @param  autoFlush  Whether the output buffer will be flushed
 145      *                    whenever a byte array is written, one of the
 146      *                    {@code println} methods is invoked, or a newline
 147      *                    character or byte ({@code '\n'}) is written
 148      *
 149      * @see java.io.PrintWriter#PrintWriter(java.io.OutputStream, boolean)
 150      */
 151     public PrintStream(OutputStream out, boolean autoFlush) {
 152         this(autoFlush, requireNonNull(out, "Null output stream"));
 153     }
 154 
 155     /**
 156      * Creates a new print stream, with the specified OutputStream, line
 157      * flushing, and character encoding.
 158      *
 159      * @param  out        The output stream to which values and objects will be
 160      *                    printed
 161      * @param  autoFlush  Whether the output buffer will be flushed
 162      *                    whenever a byte array is written, one of the
 163      *                    {@code println} methods is invoked, or a newline
 164      *                    character or byte ({@code '\n'}) is written
 165      * @param  encoding   The name of a supported
 166      *                    <a href="../lang/package-summary.html#charenc">
 167      *                    character encoding</a>
 168      *
 169      * @throws  UnsupportedEncodingException
 170      *          If the named encoding is not supported
 171      *
 172      * @since  1.4
 173      */
 174     public PrintStream(OutputStream out, boolean autoFlush, String encoding)
 175         throws UnsupportedEncodingException
 176     {
 177         this(requireNonNull(out, "Null output stream"), autoFlush, toCharset(encoding));
 178     }
 179 
 180     /**
 181      * Creates a new print stream, with the specified OutputStream, line
 182      * flushing and charset.  This convenience constructor creates the necessary
 183      * intermediate {@link java.io.OutputStreamWriter OutputStreamWriter},
 184      * which will encode characters using the provided charset.
 185      *
 186      * @param  out        The output stream to which values and objects will be
 187      *                    printed
 188      * @param  autoFlush  Whether the output buffer will be flushed
 189      *                    whenever a byte array is written, one of the
 190      *                    {@code println} methods is invoked, or a newline
 191      *                    character or byte ({@code '\n'}) is written
 192      * @param  charset    A {@linkplain java.nio.charset.Charset charset}
 193      *
 194      * @since  10
 195      */
 196     public PrintStream(OutputStream out, boolean autoFlush, Charset charset) {
 197         super(out);
 198         this.autoFlush = autoFlush;
 199         this.charOut = new OutputStreamWriter(this, charset);
 200         this.textOut = new BufferedWriter(charOut);
 201     }
 202 
 203     /**
 204      * Creates a new print stream, without automatic line flushing, with the
 205      * specified file name.  This convenience constructor creates
 206      * the necessary intermediate {@link java.io.OutputStreamWriter
 207      * OutputStreamWriter}, which will encode characters using the
 208      * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}
 209      * for this instance of the Java virtual machine.
 210      *
 211      * @param  fileName
 212      *         The name of the file to use as the destination of this print
 213      *         stream.  If the file exists, then it will be truncated to
 214      *         zero size; otherwise, a new file will be created.  The output
 215      *         will be written to the file and is buffered.
 216      *
 217      * @throws  FileNotFoundException
 218      *          If the given file object does not denote an existing, writable
 219      *          regular file and a new regular file of that name cannot be
 220      *          created, or if some other error occurs while opening or
 221      *          creating the file
 222      *
 223      * @throws  SecurityException
 224      *          If a security manager is present and {@link
 225      *          SecurityManager#checkWrite checkWrite(fileName)} denies write
 226      *          access to the file
 227      *
 228      * @since  1.5
 229      */
 230     public PrintStream(String fileName) throws FileNotFoundException {
 231         this(false, new FileOutputStream(fileName));
 232     }
 233 
 234     /**
 235      * Creates a new print stream, without automatic line flushing, with the
 236      * specified file name and charset.  This convenience constructor creates
 237      * the necessary intermediate {@link java.io.OutputStreamWriter
 238      * OutputStreamWriter}, which will encode characters using the provided
 239      * charset.
 240      *
 241      * @param  fileName
 242      *         The name of the file to use as the destination of this print
 243      *         stream.  If the file exists, then it will be truncated to
 244      *         zero size; otherwise, a new file will be created.  The output
 245      *         will be written to the file and is buffered.
 246      *
 247      * @param  csn
 248      *         The name of a supported {@linkplain java.nio.charset.Charset
 249      *         charset}
 250      *
 251      * @throws  FileNotFoundException
 252      *          If the given file object does not denote an existing, writable
 253      *          regular file and a new regular file of that name cannot be
 254      *          created, or if some other error occurs while opening or
 255      *          creating the file
 256      *
 257      * @throws  SecurityException
 258      *          If a security manager is present and {@link
 259      *          SecurityManager#checkWrite checkWrite(fileName)} denies write
 260      *          access to the file
 261      *
 262      * @throws  UnsupportedEncodingException
 263      *          If the named charset is not supported
 264      *
 265      * @since  1.5
 266      */
 267     public PrintStream(String fileName, String csn)
 268         throws FileNotFoundException, UnsupportedEncodingException
 269     {
 270         // ensure charset is checked before the file is opened
 271         this(false, toCharset(csn), new FileOutputStream(fileName));
 272     }
 273 
 274     /**
 275      * Creates a new print stream, without automatic line flushing, with the
 276      * specified file name and charset.  This convenience constructor creates
 277      * the necessary intermediate {@link java.io.OutputStreamWriter
 278      * OutputStreamWriter}, which will encode characters using the provided
 279      * charset.
 280      *
 281      * @param  fileName
 282      *         The name of the file to use as the destination of this print
 283      *         stream.  If the file exists, then it will be truncated to
 284      *         zero size; otherwise, a new file will be created.  The output
 285      *         will be written to the file and is buffered.
 286      *
 287      * @param  charset
 288      *         A {@linkplain java.nio.charset.Charset charset}
 289      *
 290      * @throws  IOException
 291      *          if an I/O error occurs while opening or creating the file
 292      *
 293      * @throws  SecurityException
 294      *          If a security manager is present and {@link
 295      *          SecurityManager#checkWrite checkWrite(fileName)} denies write
 296      *          access to the file
 297      *
 298      * @since  10
 299      */
 300     public PrintStream(String fileName, Charset charset) throws IOException {
 301         this(false, requireNonNull(charset, "charset"), new FileOutputStream(fileName));
 302     }
 303 
 304     /**
 305      * Creates a new print stream, without automatic line flushing, with the
 306      * specified file.  This convenience constructor creates the necessary
 307      * intermediate {@link java.io.OutputStreamWriter OutputStreamWriter},
 308      * which will encode characters using the {@linkplain
 309      * java.nio.charset.Charset#defaultCharset() default charset} for this
 310      * instance of the Java virtual machine.
 311      *
 312      * @param  file
 313      *         The file to use as the destination of this print stream.  If the
 314      *         file exists, then it will be truncated to zero size; otherwise,
 315      *         a new file will be created.  The output will be written to the
 316      *         file and is buffered.
 317      *
 318      * @throws  FileNotFoundException
 319      *          If the given file object does not denote an existing, writable
 320      *          regular file and a new regular file of that name cannot be
 321      *          created, or if some other error occurs while opening or
 322      *          creating the file
 323      *
 324      * @throws  SecurityException
 325      *          If a security manager is present and {@link
 326      *          SecurityManager#checkWrite checkWrite(file.getPath())}
 327      *          denies write access to the file
 328      *
 329      * @since  1.5
 330      */
 331     public PrintStream(File file) throws FileNotFoundException {
 332         this(false, new FileOutputStream(file));
 333     }
 334 
 335     /**
 336      * Creates a new print stream, without automatic line flushing, with the
 337      * specified file and charset.  This convenience constructor creates
 338      * the necessary intermediate {@link java.io.OutputStreamWriter
 339      * OutputStreamWriter}, which will encode characters using the provided
 340      * charset.
 341      *
 342      * @param  file
 343      *         The file to use as the destination of this print stream.  If the
 344      *         file exists, then it will be truncated to zero size; otherwise,
 345      *         a new file will be created.  The output will be written to the
 346      *         file and is buffered.
 347      *
 348      * @param  csn
 349      *         The name of a supported {@linkplain java.nio.charset.Charset
 350      *         charset}
 351      *
 352      * @throws  FileNotFoundException
 353      *          If the given file object does not denote an existing, writable
 354      *          regular file and a new regular file of that name cannot be
 355      *          created, or if some other error occurs while opening or
 356      *          creating the file
 357      *
 358      * @throws  SecurityException
 359      *          If a security manager is present and {@link
 360      *          SecurityManager#checkWrite checkWrite(file.getPath())}
 361      *          denies write access to the file
 362      *
 363      * @throws  UnsupportedEncodingException
 364      *          If the named charset is not supported
 365      *
 366      * @since  1.5
 367      */
 368     public PrintStream(File file, String csn)
 369         throws FileNotFoundException, UnsupportedEncodingException
 370     {
 371         // ensure charset is checked before the file is opened
 372         this(false, toCharset(csn), new FileOutputStream(file));
 373     }
 374 
 375 
 376     /**
 377      * Creates a new print stream, without automatic line flushing, with the
 378      * specified file and charset.  This convenience constructor creates
 379      * the necessary intermediate {@link java.io.OutputStreamWriter
 380      * OutputStreamWriter}, which will encode characters using the provided
 381      * charset.
 382      *
 383      * @param  file
 384      *         The file to use as the destination of this print stream.  If the
 385      *         file exists, then it will be truncated to zero size; otherwise,
 386      *         a new file will be created.  The output will be written to the
 387      *         file and is buffered.
 388      *
 389      * @param  charset
 390      *         A {@linkplain java.nio.charset.Charset charset}
 391      *
 392      * @throws  IOException
 393      *          if an I/O error occurs while opening or creating the file
 394      *
 395      * @throws  SecurityException
 396      *          If a security manager is present and {@link
 397      *          SecurityManager#checkWrite checkWrite(file.getPath())}
 398      *          denies write access to the file
 399      *
 400      * @since  10
 401      */
 402     public PrintStream(File file, Charset charset) throws IOException {
 403         this(false, requireNonNull(charset, "charset"), new FileOutputStream(file));
 404     }
 405 
 406     /** Check to make sure that the stream has not been closed */
 407     private void ensureOpen() throws IOException {
 408         if (out == null)
 409             throw new IOException("Stream closed");
 410     }
 411 
 412     /**
 413      * Flushes the stream.  This is done by writing any buffered output bytes to
 414      * the underlying output stream and then flushing that stream.
 415      *
 416      * @see        java.io.OutputStream#flush()
 417      */
 418     public void flush() {
 419         synchronized (this) {
 420             try {
 421                 ensureOpen();
 422                 out.flush();
 423             }
 424             catch (IOException x) {
 425                 trouble = true;
 426             }
 427         }
 428     }
 429 
 430     private boolean closing = false; /* To avoid recursive closing */
 431 
 432     /**
 433      * Closes the stream.  This is done by flushing the stream and then closing
 434      * the underlying output stream.
 435      *
 436      * @see        java.io.OutputStream#close()
 437      */
 438     public void close() {
 439         synchronized (this) {
 440             if (! closing) {
 441                 closing = true;
 442                 try {
 443                     textOut.close();
 444                     out.close();
 445                 }
 446                 catch (IOException x) {
 447                     trouble = true;
 448                 }
 449                 textOut = null;
 450                 charOut = null;
 451                 out = null;
 452             }
 453         }
 454     }
 455 
 456     /**
 457      * Flushes the stream and checks its error state. The internal error state
 458      * is set to {@code true} when the underlying output stream throws an
 459      * {@code IOException} other than {@code InterruptedIOException},
 460      * and when the {@code setError} method is invoked.  If an operation
 461      * on the underlying output stream throws an
 462      * {@code InterruptedIOException}, then the {@code PrintStream}
 463      * converts the exception back into an interrupt by doing:
 464      * <pre>{@code
 465      *     Thread.currentThread().interrupt();
 466      * }</pre>
 467      * or the equivalent.
 468      *
 469      * @return {@code true} if and only if this stream has encountered an
 470      *         {@code IOException} other than
 471      *         {@code InterruptedIOException}, or the
 472      *         {@code setError} method has been invoked
 473      */
 474     public boolean checkError() {
 475         if (out != null)
 476             flush();
 477         if (out instanceof java.io.PrintStream) {
 478             PrintStream ps = (PrintStream) out;
 479             return ps.checkError();
 480         }
 481         return trouble;
 482     }
 483 
 484     /**
 485      * Sets the error state of the stream to {@code true}.
 486      *
 487      * <p> This method will cause subsequent invocations of {@link
 488      * #checkError()} to return {@code true} until
 489      * {@link #clearError()} is invoked.
 490      *
 491      * @since 1.1
 492      */
 493     protected void setError() {
 494         trouble = true;
 495     }
 496 
 497     /**
 498      * Clears the internal error state of this stream.
 499      *
 500      * <p> This method will cause subsequent invocations of {@link
 501      * #checkError()} to return {@code false} until another write
 502      * operation fails and invokes {@link #setError()}.
 503      *
 504      * @since 1.6
 505      */
 506     protected void clearError() {
 507         trouble = false;
 508     }
 509 
 510     /*
 511      * Exception-catching, synchronized output operations,
 512      * which also implement the write() methods of OutputStream
 513      */
 514 
 515     /**
 516      * Writes the specified byte to this stream.  If the byte is a newline and
 517      * automatic flushing is enabled then the {@code flush} method will be
 518      * invoked.
 519      *
 520      * <p> Note that the byte is written as given; to write a character that
 521      * will be translated according to the platform's default character
 522      * encoding, use the {@code print(char)} or {@code println(char)}
 523      * methods.
 524      *
 525      * @param  b  The byte to be written
 526      * @see #print(char)
 527      * @see #println(char)
 528      */
 529     public void write(int b) {
 530         try {
 531             synchronized (this) {
 532                 ensureOpen();
 533                 out.write(b);
 534                 if ((b == '\n') && autoFlush)
 535                     out.flush();
 536             }
 537         }
 538         catch (InterruptedIOException x) {
 539             Thread.currentThread().interrupt();
 540         }
 541         catch (IOException x) {
 542             trouble = true;
 543         }
 544     }
 545 
 546     /**
 547      * Writes {@code len} bytes from the specified byte array starting at
 548      * offset {@code off} to this stream.  If automatic flushing is
 549      * enabled then the {@code flush} method will be invoked.
 550      *
 551      * <p> Note that the bytes will be written as given; to write characters
 552      * that will be translated according to the platform's default character
 553      * encoding, use the {@code print(char)} or {@code println(char)}
 554      * methods.
 555      *
 556      * @param  buf   A byte array
 557      * @param  off   Offset from which to start taking bytes
 558      * @param  len   Number of bytes to write
 559      */
 560     public void write(byte buf[], int off, int len) {
 561         try {
 562             synchronized (this) {
 563                 ensureOpen();
 564                 out.write(buf, off, len);
 565                 if (autoFlush)
 566                     out.flush();
 567             }
 568         }
 569         catch (InterruptedIOException x) {
 570             Thread.currentThread().interrupt();
 571         }
 572         catch (IOException x) {
 573             trouble = true;
 574         }
 575     }
 576 
 577     /*
 578      * The following private methods on the text- and character-output streams
 579      * always flush the stream buffers, so that writes to the underlying byte
 580      * stream occur as promptly as with the original PrintStream.
 581      */
 582 
 583     private void write(char[] buf) {
 584         try {
 585             synchronized (this) {
 586                 ensureOpen();
 587                 textOut.write(buf);
 588                 textOut.flushBuffer();
 589                 charOut.flushBuffer();
 590                 if (autoFlush) {
 591                     for (int i = 0; i < buf.length; i++)
 592                         if (buf[i] == '\n') {
 593                             out.flush();
 594                             break;
 595                         }
 596                 }
 597             }
 598         } catch (InterruptedIOException x) {
 599             Thread.currentThread().interrupt();
 600         } catch (IOException x) {
 601             trouble = true;
 602         }
 603     }
 604 
 605     // Used to optimize away back-to-back flushing and synchronization when
 606     // using println, but since subclasses could exist which depend on
 607     // observing a call to print followed by newLine() we only use this if
 608     // getClass() == PrintStream.class to avoid compatibility issues.
 609     private void writeln(char[] buf) {
 610         try {
 611             synchronized (this) {
 612                 ensureOpen();
 613                 textOut.write(buf);
 614                 textOut.newLine();
 615                 textOut.flushBuffer();
 616                 charOut.flushBuffer();
 617                 if (autoFlush)
 618                     out.flush();
 619             }
 620         }
 621         catch (InterruptedIOException x) {
 622             Thread.currentThread().interrupt();
 623         }
 624         catch (IOException x) {
 625             trouble = true;
 626         }
 627     }
 628 
 629     private void write(String s) {
 630         try {
 631             synchronized (this) {
 632                 ensureOpen();
 633                 textOut.write(s);
 634                 textOut.flushBuffer();
 635                 charOut.flushBuffer();
 636                 if (autoFlush && (s.indexOf('\n') >= 0))
 637                     out.flush();
 638             }
 639         }
 640         catch (InterruptedIOException x) {
 641             Thread.currentThread().interrupt();
 642         }
 643         catch (IOException x) {
 644             trouble = true;
 645         }
 646     }
 647 
 648     // Used to optimize away back-to-back flushing and synchronization when
 649     // using println, but since subclasses could exist which depend on
 650     // observing a call to print followed by newLine we only use this if
 651     // getClass() == PrintStream.class to avoid compatibility issues.
 652     private void writeln(String s) {
 653         try {
 654             synchronized (this) {
 655                 ensureOpen();
 656                 textOut.write(s);
 657                 textOut.newLine();
 658                 textOut.flushBuffer();
 659                 charOut.flushBuffer();
 660                 if (autoFlush)
 661                     out.flush();
 662             }
 663         }
 664         catch (InterruptedIOException x) {
 665             Thread.currentThread().interrupt();
 666         }
 667         catch (IOException x) {
 668             trouble = true;
 669         }
 670     }
 671 
 672     private void newLine() {
 673         try {
 674             synchronized (this) {
 675                 ensureOpen();
 676                 textOut.newLine();
 677                 textOut.flushBuffer();
 678                 charOut.flushBuffer();
 679                 if (autoFlush)
 680                     out.flush();
 681             }
 682         }
 683         catch (InterruptedIOException x) {
 684             Thread.currentThread().interrupt();
 685         }
 686         catch (IOException x) {
 687             trouble = true;
 688         }
 689     }
 690 
 691     /* Methods that do not terminate lines */
 692 
 693     /**
 694      * Prints a boolean value.  The string produced by {@link
 695      * java.lang.String#valueOf(boolean)} is translated into bytes
 696      * according to the platform's default character encoding, and these bytes
 697      * are written in exactly the manner of the
 698      * {@link #write(int)} method.
 699      *
 700      * @param      b   The {@code boolean} to be printed
 701      */
 702     public void print(boolean b) {
 703         write(String.valueOf(b));
 704     }
 705 
 706     /**
 707      * Prints a character.  The character is translated into one or more bytes
 708      * according to the character encoding given to the constructor, or the
 709      * platform's default character encoding if none specified. These bytes
 710      * are written in exactly the manner of the {@link #write(int)} method.
 711      *
 712      * @param      c   The {@code char} to be printed
 713      */
 714     public void print(char c) {
 715         write(String.valueOf(c));
 716     }
 717 
 718     /**
 719      * Prints an integer.  The string produced by {@link
 720      * java.lang.String#valueOf(int)} is translated into bytes
 721      * according to the platform's default character encoding, and these bytes
 722      * are written in exactly the manner of the
 723      * {@link #write(int)} method.
 724      *
 725      * @param      i   The {@code int} to be printed
 726      * @see        java.lang.Integer#toString(int)
 727      */
 728     public void print(int i) {
 729         write(String.valueOf(i));
 730     }
 731 
 732     /**
 733      * Prints a long integer.  The string produced by {@link
 734      * java.lang.String#valueOf(long)} is translated into bytes
 735      * according to the platform's default character encoding, and these bytes
 736      * are written in exactly the manner of the
 737      * {@link #write(int)} method.
 738      *
 739      * @param      l   The {@code long} to be printed
 740      * @see        java.lang.Long#toString(long)
 741      */
 742     public void print(long l) {
 743         write(String.valueOf(l));
 744     }
 745 
 746     /**
 747      * Prints a floating-point number.  The string produced by {@link
 748      * java.lang.String#valueOf(float)} is translated into bytes
 749      * according to the platform's default character encoding, and these bytes
 750      * are written in exactly the manner of the
 751      * {@link #write(int)} method.
 752      *
 753      * @param      f   The {@code float} to be printed
 754      * @see        java.lang.Float#toString(float)
 755      */
 756     public void print(float f) {
 757         write(String.valueOf(f));
 758     }
 759 
 760     /**
 761      * Prints a double-precision floating-point number.  The string produced by
 762      * {@link java.lang.String#valueOf(double)} is translated into
 763      * bytes according to the platform's default character encoding, and these
 764      * bytes are written in exactly the manner of the {@link
 765      * #write(int)} method.
 766      *
 767      * @param      d   The {@code double} to be printed
 768      * @see        java.lang.Double#toString(double)
 769      */
 770     public void print(double d) {
 771         write(String.valueOf(d));
 772     }
 773 
 774     /**
 775      * Prints an array of characters.  The characters are converted into bytes
 776      * according to the character encoding given to the constructor, or the
 777      * platform's default character encoding if none specified. These bytes
 778      * are written in exactly the manner of the {@link #write(int)} method.
 779      *
 780      * @param      s   The array of chars to be printed
 781      *
 782      * @throws  NullPointerException  If {@code s} is {@code null}
 783      */
 784     public void print(char s[]) {
 785         write(s);
 786     }
 787 
 788     /**
 789      * Prints a string.  If the argument is {@code null} then the string
 790      * {@code "null"} is printed.  Otherwise, the string's characters are
 791      * converted into bytes according to the character encoding given to the
 792      * constructor, or the platform's default character encoding if none
 793      * specified. These bytes are written in exactly the manner of the
 794      * {@link #write(int)} method.
 795      *
 796      * @param      s   The {@code String} to be printed
 797      */
 798     public void print(String s) {
 799         write(String.valueOf(s));
 800     }
 801 
 802     /**
 803      * Prints an object.  The string produced by the {@link
 804      * java.lang.String#valueOf(Object)} method is translated into bytes
 805      * according to the platform's default character encoding, and these bytes
 806      * are written in exactly the manner of the
 807      * {@link #write(int)} method.
 808      *
 809      * @param      obj   The {@code Object} to be printed
 810      * @see        java.lang.Object#toString()
 811      */
 812     public void print(Object obj) {
 813         write(String.valueOf(obj));
 814     }
 815 
 816 
 817     /* Methods that do terminate lines */
 818 
 819     /**
 820      * Terminates the current line by writing the line separator string.  The
 821      * line separator string is defined by the system property
 822      * {@code line.separator}, and is not necessarily a single newline
 823      * character ({@code '\n'}).
 824      */
 825     public void println() {
 826         newLine();
 827     }
 828 
 829     /**
 830      * Prints a boolean and then terminate the line.  This method behaves as
 831      * though it invokes {@link #print(boolean)} and then
 832      * {@link #println()}.
 833      *
 834      * @param x  The {@code boolean} to be printed
 835      */
 836     public void println(boolean x) {
 837         if (getClass() == PrintStream.class) {
 838             writeln(String.valueOf(x));
 839         } else {
 840             synchronized (this) {
 841                 print(x);
 842                 newLine();
 843             }
 844         }
 845     }
 846 
 847     /**
 848      * Prints a character and then terminate the line.  This method behaves as
 849      * though it invokes {@link #print(char)} and then
 850      * {@link #println()}.
 851      *
 852      * @param x  The {@code char} to be printed.
 853      */
 854     public void println(char x) {
 855         if (getClass() == PrintStream.class) {
 856             writeln(String.valueOf(x));
 857         } else {
 858             synchronized (this) {
 859                 print(x);
 860                 newLine();
 861             }
 862         }
 863     }
 864 
 865     /**
 866      * Prints an integer and then terminate the line.  This method behaves as
 867      * though it invokes {@link #print(int)} and then
 868      * {@link #println()}.
 869      *
 870      * @param x  The {@code int} to be printed.
 871      */
 872     public void println(int x) {
 873         if (getClass() == PrintStream.class) {
 874             writeln(String.valueOf(x));
 875         } else {
 876             synchronized (this) {
 877                 print(x);
 878                 newLine();
 879             }
 880         }
 881     }
 882 
 883     /**
 884      * Prints a long and then terminate the line.  This method behaves as
 885      * though it invokes {@link #print(long)} and then
 886      * {@link #println()}.
 887      *
 888      * @param x  a The {@code long} to be printed.
 889      */
 890     public void println(long x) {
 891         if (getClass() == PrintStream.class) {
 892             writeln(String.valueOf(x));
 893         } else {
 894             synchronized (this) {
 895                 print(x);
 896                 newLine();
 897             }
 898         }
 899     }
 900 
 901     /**
 902      * Prints a float and then terminate the line.  This method behaves as
 903      * though it invokes {@link #print(float)} and then
 904      * {@link #println()}.
 905      *
 906      * @param x  The {@code float} to be printed.
 907      */
 908     public void println(float x) {
 909         if (getClass() == PrintStream.class) {
 910             writeln(String.valueOf(x));
 911         } else {
 912             synchronized (this) {
 913                 print(x);
 914                 newLine();
 915             }
 916         }
 917     }
 918 
 919     /**
 920      * Prints a double and then terminate the line.  This method behaves as
 921      * though it invokes {@link #print(double)} and then
 922      * {@link #println()}.
 923      *
 924      * @param x  The {@code double} to be printed.
 925      */
 926     public void println(double x) {
 927         if (getClass() == PrintStream.class) {
 928             writeln(String.valueOf(x));
 929         } else {
 930             synchronized (this) {
 931                 print(x);
 932                 newLine();
 933             }
 934         }
 935     }
 936 
 937     /**
 938      * Prints an array of characters and then terminate the line.  This method
 939      * behaves as though it invokes {@link #print(char[])} and
 940      * then {@link #println()}.
 941      *
 942      * @param x  an array of chars to print.
 943      */
 944     public void println(char[] x) {
 945         if (getClass() == PrintStream.class) {
 946             writeln(x);
 947         } else {
 948             synchronized (this) {
 949                 print(x);
 950                 newLine();
 951             }
 952         }
 953     }
 954 
 955     /**
 956      * Prints a String and then terminate the line.  This method behaves as
 957      * though it invokes {@link #print(String)} and then
 958      * {@link #println()}.
 959      *
 960      * @param x  The {@code String} to be printed.
 961      */
 962     public void println(String x) {
 963         if (getClass() == PrintStream.class) {
 964             writeln(String.valueOf(x));
 965         } else {
 966             synchronized (this) {
 967                 print(x);
 968                 newLine();
 969             }
 970         }
 971     }
 972 
 973     /**
 974      * Prints an Object and then terminate the line.  This method calls
 975      * at first String.valueOf(x) to get the printed object's string value,
 976      * then behaves as
 977      * though it invokes {@link #print(String)} and then
 978      * {@link #println()}.
 979      *
 980      * @param x  The {@code Object} to be printed.
 981      */
 982     public void println(Object x) {
 983         String s = String.valueOf(x);
 984         if (getClass() == PrintStream.class) {
 985             // need to apply String.valueOf again since first invocation
 986             // might return null
 987             writeln(String.valueOf(s));
 988         } else {
 989             synchronized (this) {
 990                 print(s);
 991                 newLine();
 992             }
 993         }
 994     }
 995 
 996 
 997     /**
 998      * A convenience method to write a formatted string to this output stream
 999      * using the specified format string and arguments.
1000      *
1001      * <p> An invocation of this method of the form
1002      * {@code out.printf(format, args)} behaves
1003      * in exactly the same way as the invocation
1004      *
1005      * <pre>{@code
1006      *     out.format(format, args)
1007      * }</pre>
1008      *
1009      * @param  format
1010      *         A format string as described in <a
1011      *         href="../util/Formatter.html#syntax">Format string syntax</a>
1012      *
1013      * @param  args
1014      *         Arguments referenced by the format specifiers in the format
1015      *         string.  If there are more arguments than format specifiers, the
1016      *         extra arguments are ignored.  The number of arguments is
1017      *         variable and may be zero.  The maximum number of arguments is
1018      *         limited by the maximum dimension of a Java array as defined by
1019      *         <cite>The Java&trade; Virtual Machine Specification</cite>.
1020      *         The behaviour on a
1021      *         {@code null} argument depends on the <a
1022      *         href="../util/Formatter.html#syntax">conversion</a>.
1023      *
1024      * @throws  java.util.IllegalFormatException
1025      *          If a format string contains an illegal syntax, a format
1026      *          specifier that is incompatible with the given arguments,
1027      *          insufficient arguments given the format string, or other
1028      *          illegal conditions.  For specification of all possible
1029      *          formatting errors, see the <a
1030      *          href="../util/Formatter.html#detail">Details</a> section of the
1031      *          formatter class specification.
1032      *
1033      * @throws  NullPointerException
1034      *          If the {@code format} is {@code null}
1035      *
1036      * @return  This output stream
1037      *
1038      * @since  1.5
1039      */
1040     public PrintStream printf(String format, Object ... args) {
1041         return format(format, args);
1042     }
1043 
1044     /**
1045      * A convenience method to write a formatted string to this output stream
1046      * using the specified format string and arguments.
1047      *
1048      * <p> An invocation of this method of the form
1049      * {@code out.printf(l, format, args)} behaves
1050      * in exactly the same way as the invocation
1051      *
1052      * <pre>{@code
1053      *     out.format(l, format, args)
1054      * }</pre>
1055      *
1056      * @param  l
1057      *         The {@linkplain java.util.Locale locale} to apply during
1058      *         formatting.  If {@code l} is {@code null} then no localization
1059      *         is applied.
1060      *
1061      * @param  format
1062      *         A format string as described in <a
1063      *         href="../util/Formatter.html#syntax">Format string syntax</a>
1064      *
1065      * @param  args
1066      *         Arguments referenced by the format specifiers in the format
1067      *         string.  If there are more arguments than format specifiers, the
1068      *         extra arguments are ignored.  The number of arguments is
1069      *         variable and may be zero.  The maximum number of arguments is
1070      *         limited by the maximum dimension of a Java array as defined by
1071      *         <cite>The Java&trade; Virtual Machine Specification</cite>.
1072      *         The behaviour on a
1073      *         {@code null} argument depends on the <a
1074      *         href="../util/Formatter.html#syntax">conversion</a>.
1075      *
1076      * @throws  java.util.IllegalFormatException
1077      *          If a format string contains an illegal syntax, a format
1078      *          specifier that is incompatible with the given arguments,
1079      *          insufficient arguments given the format string, or other
1080      *          illegal conditions.  For specification of all possible
1081      *          formatting errors, see the <a
1082      *          href="../util/Formatter.html#detail">Details</a> section of the
1083      *          formatter class specification.
1084      *
1085      * @throws  NullPointerException
1086      *          If the {@code format} is {@code null}
1087      *
1088      * @return  This output stream
1089      *
1090      * @since  1.5
1091      */
1092     public PrintStream printf(Locale l, String format, Object ... args) {
1093         return format(l, format, args);
1094     }
1095 
1096     /**
1097      * Writes a formatted string to this output stream using the specified
1098      * format string and arguments.
1099      *
1100      * <p> The locale always used is the one returned by {@link
1101      * java.util.Locale#getDefault(Locale.Category)} with
1102      * {@link java.util.Locale.Category#FORMAT FORMAT} category specified,
1103      * regardless of any previous invocations of other formatting methods on
1104      * this object.
1105      *
1106      * @param  format
1107      *         A format string as described in <a
1108      *         href="../util/Formatter.html#syntax">Format string syntax</a>
1109      *
1110      * @param  args
1111      *         Arguments referenced by the format specifiers in the format
1112      *         string.  If there are more arguments than format specifiers, the
1113      *         extra arguments are ignored.  The number of arguments is
1114      *         variable and may be zero.  The maximum number of arguments is
1115      *         limited by the maximum dimension of a Java array as defined by
1116      *         <cite>The Java&trade; Virtual Machine Specification</cite>.
1117      *         The behaviour on a
1118      *         {@code null} argument depends on the <a
1119      *         href="../util/Formatter.html#syntax">conversion</a>.
1120      *
1121      * @throws  java.util.IllegalFormatException
1122      *          If a format string contains an illegal syntax, a format
1123      *          specifier that is incompatible with the given arguments,
1124      *          insufficient arguments given the format string, or other
1125      *          illegal conditions.  For specification of all possible
1126      *          formatting errors, see the <a
1127      *          href="../util/Formatter.html#detail">Details</a> section of the
1128      *          formatter class specification.
1129      *
1130      * @throws  NullPointerException
1131      *          If the {@code format} is {@code null}
1132      *
1133      * @return  This output stream
1134      *
1135      * @since  1.5
1136      */
1137     public PrintStream format(String format, Object ... args) {
1138         try {
1139             synchronized (this) {
1140                 ensureOpen();
1141                 if ((formatter == null)
1142                     || (formatter.locale() !=
1143                         Locale.getDefault(Locale.Category.FORMAT)))
1144                     formatter = new Formatter((Appendable) this);
1145                 formatter.format(Locale.getDefault(Locale.Category.FORMAT),
1146                                  format, args);
1147             }
1148         } catch (InterruptedIOException x) {
1149             Thread.currentThread().interrupt();
1150         } catch (IOException x) {
1151             trouble = true;
1152         }
1153         return this;
1154     }
1155 
1156     /**
1157      * Writes a formatted string to this output stream using the specified
1158      * format string and arguments.
1159      *
1160      * @param  l
1161      *         The {@linkplain java.util.Locale locale} to apply during
1162      *         formatting.  If {@code l} is {@code null} then no localization
1163      *         is applied.
1164      *
1165      * @param  format
1166      *         A format string as described in <a
1167      *         href="../util/Formatter.html#syntax">Format string syntax</a>
1168      *
1169      * @param  args
1170      *         Arguments referenced by the format specifiers in the format
1171      *         string.  If there are more arguments than format specifiers, the
1172      *         extra arguments are ignored.  The number of arguments is
1173      *         variable and may be zero.  The maximum number of arguments is
1174      *         limited by the maximum dimension of a Java array as defined by
1175      *         <cite>The Java&trade; Virtual Machine Specification</cite>.
1176      *         The behaviour on a
1177      *         {@code null} argument depends on the <a
1178      *         href="../util/Formatter.html#syntax">conversion</a>.
1179      *
1180      * @throws  java.util.IllegalFormatException
1181      *          If a format string contains an illegal syntax, a format
1182      *          specifier that is incompatible with the given arguments,
1183      *          insufficient arguments given the format string, or other
1184      *          illegal conditions.  For specification of all possible
1185      *          formatting errors, see the <a
1186      *          href="../util/Formatter.html#detail">Details</a> section of the
1187      *          formatter class specification.
1188      *
1189      * @throws  NullPointerException
1190      *          If the {@code format} is {@code null}
1191      *
1192      * @return  This output stream
1193      *
1194      * @since  1.5
1195      */
1196     public PrintStream format(Locale l, String format, Object ... args) {
1197         try {
1198             synchronized (this) {
1199                 ensureOpen();
1200                 if ((formatter == null)
1201                     || (formatter.locale() != l))
1202                     formatter = new Formatter(this, l);
1203                 formatter.format(l, format, args);
1204             }
1205         } catch (InterruptedIOException x) {
1206             Thread.currentThread().interrupt();
1207         } catch (IOException x) {
1208             trouble = true;
1209         }
1210         return this;
1211     }
1212 
1213     /**
1214      * Appends the specified character sequence to this output stream.
1215      *
1216      * <p> An invocation of this method of the form {@code out.append(csq)}
1217      * behaves in exactly the same way as the invocation
1218      *
1219      * <pre>{@code
1220      *     out.print(csq.toString())
1221      * }</pre>
1222      *
1223      * <p> Depending on the specification of {@code toString} for the
1224      * character sequence {@code csq}, the entire sequence may not be
1225      * appended.  For instance, invoking then {@code toString} method of a
1226      * character buffer will return a subsequence whose content depends upon
1227      * the buffer's position and limit.
1228      *
1229      * @param  csq
1230      *         The character sequence to append.  If {@code csq} is
1231      *         {@code null}, then the four characters {@code "null"} are
1232      *         appended to this output stream.
1233      *
1234      * @return  This output stream
1235      *
1236      * @since  1.5
1237      */
1238     public PrintStream append(CharSequence csq) {
1239         print(String.valueOf(csq));
1240         return this;
1241     }
1242 
1243     /**
1244      * Appends a subsequence of the specified character sequence to this output
1245      * stream.
1246      *
1247      * <p> An invocation of this method of the form
1248      * {@code out.append(csq, start, end)} when
1249      * {@code csq} is not {@code null}, behaves in
1250      * exactly the same way as the invocation
1251      *
1252      * <pre>{@code
1253      *     out.print(csq.subSequence(start, end).toString())
1254      * }</pre>
1255      *
1256      * @param  csq
1257      *         The character sequence from which a subsequence will be
1258      *         appended.  If {@code csq} is {@code null}, then characters
1259      *         will be appended as if {@code csq} contained the four
1260      *         characters {@code "null"}.
1261      *
1262      * @param  start
1263      *         The index of the first character in the subsequence
1264      *
1265      * @param  end
1266      *         The index of the character following the last character in the
1267      *         subsequence
1268      *
1269      * @return  This output stream
1270      *
1271      * @throws  IndexOutOfBoundsException
1272      *          If {@code start} or {@code end} are negative, {@code start}
1273      *          is greater than {@code end}, or {@code end} is greater than
1274      *          {@code csq.length()}
1275      *
1276      * @since  1.5
1277      */
1278     public PrintStream append(CharSequence csq, int start, int end) {
1279         if (csq == null) csq = "null";
1280         return append(csq.subSequence(start, end));
1281     }
1282 
1283     /**
1284      * Appends the specified character to this output stream.
1285      *
1286      * <p> An invocation of this method of the form {@code out.append(c)}
1287      * behaves in exactly the same way as the invocation
1288      *
1289      * <pre>{@code
1290      *     out.print(c)
1291      * }</pre>
1292      *
1293      * @param  c
1294      *         The 16-bit character to append
1295      *
1296      * @return  This output stream
1297      *
1298      * @since  1.5
1299      */
1300     public PrintStream append(char c) {
1301         print(c);
1302         return this;
1303     }
1304 
1305 }