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