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