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