< prev index next >

src/java.base/share/classes/java/io/PrintStream.java

Print this page

  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.io;
  27 
  28 import java.util.Formatter;
  29 import java.util.Locale;
  30 import java.nio.charset.Charset;
  31 import java.nio.charset.IllegalCharsetNameException;
  32 import java.nio.charset.UnsupportedCharsetException;



  33 
  34 /**
  35  * A {@code PrintStream} adds functionality to another output stream,
  36  * namely the ability to print representations of various data values
  37  * conveniently.  Two other features are provided as well.  Unlike other output
  38  * streams, a {@code PrintStream} never throws an
  39  * {@code IOException}; instead, exceptional situations merely set an
  40  * internal flag that can be tested via the {@code checkError} method.
  41  * Optionally, a {@code PrintStream} can be created so as to flush
  42  * automatically; this means that the {@code flush} method of the underlying
  43  * output stream is automatically invoked after a byte array is written, one
  44  * of the {@code println} methods is invoked, or a newline character or byte
  45  * ({@code '\n'}) is written.
  46  *
  47  * <p> All characters printed by a {@code PrintStream} are converted into
  48  * bytes using the given encoding or charset, or the default charset if not
  49  * specified.
  50  * The {@link PrintWriter} class should be used in situations that require
  51  * writing characters rather than bytes.
  52  *
  53  * <p> This class always replaces malformed and unmappable character sequences
  54  * with the charset's default replacement string.
  55  * The {@linkplain java.nio.charset.CharsetEncoder} class should be used when more
  56  * control over the encoding process is required.
  57  *
  58  * @author     Frank Yellin
  59  * @author     Mark Reinhold
  60  * @since      1.0
  61  * @see Charset#defaultCharset()
  62  */
  63 
  64 public class PrintStream extends FilterOutputStream
  65     implements Appendable, Closeable
  66 {


  67 
  68     private final boolean autoFlush;
  69     private boolean trouble = false;
  70     private Formatter formatter;
  71 
  72     /**
  73      * Track both the text- and character-output streams, so that their buffers
  74      * can be flushed without flushing the entire stream.
  75      */
  76     private BufferedWriter textOut;
  77     private OutputStreamWriter charOut;
  78 
  79     /**
  80      * requireNonNull is explicitly declared here so as not to create an extra
  81      * dependency on java.util.Objects.requireNonNull. PrintStream is loaded
  82      * early during system initialization.
  83      */
  84     private static <T> T requireNonNull(T obj, String message) {
  85         if (obj == null)
  86             throw new NullPointerException(message);

  93      * @throws UnsupportedEncodingException  if the charset is not supported
  94      */
  95     private static Charset toCharset(String csn)
  96         throws UnsupportedEncodingException
  97     {
  98         requireNonNull(csn, "charsetName");
  99         try {
 100             return Charset.forName(csn);
 101         } catch (IllegalCharsetNameException|UnsupportedCharsetException unused) {
 102             // UnsupportedEncodingException should be thrown
 103             throw new UnsupportedEncodingException(csn);
 104         }
 105     }
 106 
 107     /* Private constructors */
 108     private PrintStream(boolean autoFlush, OutputStream out) {
 109         super(out);
 110         this.autoFlush = autoFlush;
 111         this.charOut = new OutputStreamWriter(this);
 112         this.textOut = new BufferedWriter(charOut);







 113     }
 114 
 115     /* Variant of the private constructor so that the given charset name
 116      * can be verified before evaluating the OutputStream argument. Used
 117      * by constructors creating a FileOutputStream that also take a
 118      * charset name.
 119      */
 120     private PrintStream(boolean autoFlush, Charset charset, OutputStream out) {
 121         this(out, autoFlush, charset);
 122     }
 123 
 124     /**
 125      * Creates a new print stream, without automatic line flushing, with the
 126      * specified OutputStream. Characters written to the stream are converted
 127      * to bytes using the default charset.
 128      *
 129      * @param  out        The output stream to which values and objects will be
 130      *                    printed
 131      *
 132      * @see java.io.PrintWriter#PrintWriter(java.io.OutputStream)

 184      * Creates a new print stream, with the specified OutputStream, line
 185      * flushing and charset.  This convenience constructor creates the necessary
 186      * intermediate {@link java.io.OutputStreamWriter OutputStreamWriter},
 187      * which will encode characters using the provided charset.
 188      *
 189      * @param  out        The output stream to which values and objects will be
 190      *                    printed
 191      * @param  autoFlush  Whether the output buffer will be flushed
 192      *                    whenever a byte array is written, one of the
 193      *                    {@code println} methods is invoked, or a newline
 194      *                    character or byte ({@code '\n'}) is written
 195      * @param  charset    A {@linkplain Charset charset}
 196      *
 197      * @since  10
 198      */
 199     public PrintStream(OutputStream out, boolean autoFlush, Charset charset) {
 200         super(out);
 201         this.autoFlush = autoFlush;
 202         this.charOut = new OutputStreamWriter(this, charset);
 203         this.textOut = new BufferedWriter(charOut);







 204     }
 205 
 206     /**
 207      * Creates a new print stream, without automatic line flushing, with the
 208      * specified file name.  This convenience constructor creates
 209      * the necessary intermediate {@link java.io.OutputStreamWriter
 210      * OutputStreamWriter}, which will encode characters using the
 211      * {@linkplain Charset#defaultCharset() default charset}
 212      * for this instance of the Java virtual machine.
 213      *
 214      * @param  fileName
 215      *         The name of the file to use as the destination of this print
 216      *         stream.  If the file exists, then it will be truncated to
 217      *         zero size; otherwise, a new file will be created.  The output
 218      *         will be written to the file and is buffered.
 219      *
 220      * @throws  FileNotFoundException
 221      *          If the given file object does not denote an existing, writable
 222      *          regular file and a new regular file of that name cannot be
 223      *          created, or if some other error occurs while opening or

 403      * @since  10
 404      */
 405     public PrintStream(File file, Charset charset) throws IOException {
 406         this(false, requireNonNull(charset, "charset"), new FileOutputStream(file));
 407     }
 408 
 409     /** Check to make sure that the stream has not been closed */
 410     private void ensureOpen() throws IOException {
 411         if (out == null)
 412             throw new IOException("Stream closed");
 413     }
 414 
 415     /**
 416      * Flushes the stream.  This is done by writing any buffered output bytes to
 417      * the underlying output stream and then flushing that stream.
 418      *
 419      * @see        java.io.OutputStream#flush()
 420      */
 421     @Override
 422     public void flush() {
 423         synchronized (this) {

 424             try {
 425                 ensureOpen();
 426                 out.flush();

 427             }
 428             catch (IOException x) {
 429                 trouble = true;

 430             }
 431         }
 432     }










 433 
 434     private boolean closing = false; /* To avoid recursive closing */
 435 
 436     /**
 437      * Closes the stream.  This is done by flushing the stream and then closing
 438      * the underlying output stream.
 439      *
 440      * @see        java.io.OutputStream#close()
 441      */
 442     @Override
 443     public void close() {
 444         synchronized (this) {
 445             if (! closing) {
 446                 closing = true;
 447                 try {
 448                     textOut.close();
 449                     out.close();
 450                 }
 451                 catch (IOException x) {
 452                     trouble = true;
 453                 }
 454                 textOut = null;
 455                 charOut = null;
 456                 out = null;










 457             }



 458         }
 459     }
 460 
 461     /**
 462      * Flushes the stream and checks its error state. The internal error state
 463      * is set to {@code true} when the underlying output stream throws an
 464      * {@code IOException} other than {@code InterruptedIOException},
 465      * and when the {@code setError} method is invoked.  If an operation
 466      * on the underlying output stream throws an
 467      * {@code InterruptedIOException}, then the {@code PrintStream}
 468      * converts the exception back into an interrupt by doing:
 469      * <pre>{@code
 470      *     Thread.currentThread().interrupt();
 471      * }</pre>
 472      * or the equivalent.
 473      *
 474      * @return {@code true} if and only if this stream has encountered an
 475      *         {@code IOException} other than
 476      *         {@code InterruptedIOException}, or the
 477      *         {@code setError} method has been invoked

 515      * Exception-catching, synchronized output operations,
 516      * which also implement the write() methods of OutputStream
 517      */
 518 
 519     /**
 520      * Writes the specified byte to this stream.  If the byte is a newline and
 521      * automatic flushing is enabled then the {@code flush} method will be
 522      * invoked on the underlying output stream.
 523      *
 524      * <p> Note that the byte is written as given; to write a character that
 525      * will be translated according to the default charset, use the
 526      * {@code print(char)} or {@code println(char)} methods.
 527      *
 528      * @param  b  The byte to be written
 529      * @see #print(char)
 530      * @see #println(char)
 531      */
 532     @Override
 533     public void write(int b) {
 534         try {
 535             synchronized (this) {
 536                 ensureOpen();
 537                 out.write(b);
 538                 if ((b == '\n') && autoFlush)
 539                     out.flush();






 540             }
 541         }
 542         catch (InterruptedIOException x) {
 543             Thread.currentThread().interrupt();
 544         }
 545         catch (IOException x) {
 546             trouble = true;
 547         }
 548     }







 549 
 550     /**
 551      * Writes {@code len} bytes from the specified byte array starting at
 552      * offset {@code off} to this stream.  If automatic flushing is
 553      * enabled then the {@code flush} method will be invoked on the underlying
 554      * output stream.
 555      *
 556      * <p> Note that the bytes will be written as given; to write characters
 557      * that will be translated according to the default charset, use the
 558      * {@code print(char)} or {@code println(char)} methods.
 559      *
 560      * @param  buf   A byte array
 561      * @param  off   Offset from which to start taking bytes
 562      * @param  len   Number of bytes to write
 563      */
 564     @Override
 565     public void write(byte[] buf, int off, int len) {
 566         try {
 567             synchronized (this) {
 568                 ensureOpen();
 569                 out.write(buf, off, len);
 570                 if (autoFlush)
 571                     out.flush();






 572             }
 573         }
 574         catch (InterruptedIOException x) {
 575             Thread.currentThread().interrupt();
 576         }
 577         catch (IOException x) {
 578             trouble = true;
 579         }
 580     }
 581 








 582     /**
 583      * Writes all bytes from the specified byte array to this stream. If
 584      * automatic flushing is enabled then the {@code flush} method will be
 585      * invoked on the underlying output stream.
 586      *
 587      * <p> Note that the bytes will be written as given; to write characters
 588      * that will be translated according to the default charset, use the
 589      * {@code print(char[])} or {@code println(char[])} methods.
 590      *
 591      * @apiNote
 592      * Although declared to throw {@code IOException}, this method never
 593      * actually does so. Instead, like other methods that this class
 594      * overrides, it sets an internal flag which may be tested via the
 595      * {@link #checkError()} method. To write an array of bytes without having
 596      * to write a {@code catch} block for the {@code IOException}, use either
 597      * {@link #writeBytes(byte[] buf) writeBytes(buf)} or
 598      * {@link #write(byte[], int, int) write(buf, 0, buf.length)}.
 599      *
 600      * @implSpec
 601      * This method is equivalent to

 628      * @implSpec
 629      * This method is equivalent to
 630      * {@link #write(byte[], int, int) this.write(buf, 0, buf.length)}.
 631      *
 632      * @param  buf   A byte array
 633      *
 634      * @since 14
 635      */
 636     public void writeBytes(byte[] buf) {
 637         this.write(buf, 0, buf.length);
 638     }
 639 
 640     /*
 641      * The following private methods on the text- and character-output streams
 642      * always flush the stream buffers, so that writes to the underlying byte
 643      * stream occur as promptly as with the original PrintStream.
 644      */
 645 
 646     private void write(char[] buf) {
 647         try {
 648             synchronized (this) {
 649                 ensureOpen();
 650                 textOut.write(buf);
 651                 textOut.flushBuffer();
 652                 charOut.flushBuffer();
 653                 if (autoFlush) {
 654                     for (int i = 0; i < buf.length; i++)
 655                         if (buf[i] == '\n') {
 656                             out.flush();
 657                             break;
 658                         }
 659                 }
 660             }
 661         } catch (InterruptedIOException x) {
 662             Thread.currentThread().interrupt();
 663         } catch (IOException x) {
 664             trouble = true;
 665         }
 666     }
 667 














 668     // Used to optimize away back-to-back flushing and synchronization when
 669     // using println, but since subclasses could exist which depend on
 670     // observing a call to print followed by newLine() we only use this if
 671     // getClass() == PrintStream.class to avoid compatibility issues.
 672     private void writeln(char[] buf) {
 673         try {
 674             synchronized (this) {
 675                 ensureOpen();
 676                 textOut.write(buf);
 677                 textOut.newLine();
 678                 textOut.flushBuffer();
 679                 charOut.flushBuffer();
 680                 if (autoFlush)
 681                     out.flush();



 682             }
 683         }
 684         catch (InterruptedIOException x) {
 685             Thread.currentThread().interrupt();
 686         }
 687         catch (IOException x) {
 688             trouble = true;
 689         }
 690     }
 691 










 692     private void write(String s) {
 693         try {
 694             synchronized (this) {
 695                 ensureOpen();
 696                 textOut.write(s);
 697                 textOut.flushBuffer();
 698                 charOut.flushBuffer();
 699                 if (autoFlush && (s.indexOf('\n') >= 0))
 700                     out.flush();




 701             }
 702         }
 703         catch (InterruptedIOException x) {
 704             Thread.currentThread().interrupt();
 705         }
 706         catch (IOException x) {
 707             trouble = true;
 708         }
 709     }
 710 









 711     // Used to optimize away back-to-back flushing and synchronization when
 712     // using println, but since subclasses could exist which depend on
 713     // observing a call to print followed by newLine we only use this if
 714     // getClass() == PrintStream.class to avoid compatibility issues.
 715     private void writeln(String s) {
 716         try {
 717             synchronized (this) {
 718                 ensureOpen();
 719                 textOut.write(s);
 720                 textOut.newLine();
 721                 textOut.flushBuffer();
 722                 charOut.flushBuffer();
 723                 if (autoFlush)
 724                     out.flush();



 725             }
 726         }
 727         catch (InterruptedIOException x) {
 728             Thread.currentThread().interrupt();
 729         }
 730         catch (IOException x) {
 731             trouble = true;
 732         }
 733     }
 734 










 735     private void newLine() {
 736         try {
 737             synchronized (this) {
 738                 ensureOpen();
 739                 textOut.newLine();
 740                 textOut.flushBuffer();
 741                 charOut.flushBuffer();
 742                 if (autoFlush)
 743                     out.flush();




 744             }
 745         }
 746         catch (InterruptedIOException x) {
 747             Thread.currentThread().interrupt();
 748         }
 749         catch (IOException x) {
 750             trouble = true;
 751         }
 752     }
 753 









 754     /* Methods that do not terminate lines */
 755 
 756     /**
 757      * Prints a boolean value.  The string produced by {@link
 758      * java.lang.String#valueOf(boolean)} is translated into bytes
 759      * according to the default charset, and these bytes
 760      * are written in exactly the manner of the
 761      * {@link #write(int)} method.
 762      *
 763      * @param      b   The {@code boolean} to be printed
 764      * @see Charset#defaultCharset()
 765      */
 766     public void print(boolean b) {
 767         write(String.valueOf(b));
 768     }
 769 
 770     /**
 771      * Prints a character.  The character is translated into one or more bytes
 772      * according to the character encoding given to the constructor, or the
 773      * default charset if none specified. These bytes

1191      *         href="../util/Formatter.html#syntax">conversion</a>.
1192      *
1193      * @throws  java.util.IllegalFormatException
1194      *          If a format string contains an illegal syntax, a format
1195      *          specifier that is incompatible with the given arguments,
1196      *          insufficient arguments given the format string, or other
1197      *          illegal conditions.  For specification of all possible
1198      *          formatting errors, see the <a
1199      *          href="../util/Formatter.html#detail">Details</a> section of the
1200      *          formatter class specification.
1201      *
1202      * @throws  NullPointerException
1203      *          If the {@code format} is {@code null}
1204      *
1205      * @return  This output stream
1206      *
1207      * @since  1.5
1208      */
1209     public PrintStream format(String format, Object ... args) {
1210         try {
1211             synchronized (this) {
1212                 ensureOpen();
1213                 if ((formatter == null)
1214                     || (formatter.locale() !=
1215                         Locale.getDefault(Locale.Category.FORMAT)))
1216                     formatter = new Formatter((Appendable) this);
1217                 formatter.format(Locale.getDefault(Locale.Category.FORMAT),
1218                                  format, args);



1219             }
1220         } catch (InterruptedIOException x) {
1221             Thread.currentThread().interrupt();
1222         } catch (IOException x) {
1223             trouble = true;
1224         }
1225         return this;
1226     }
1227 







1228     /**
1229      * Writes a formatted string to this output stream using the specified
1230      * format string and arguments.
1231      *
1232      * @param  l
1233      *         The {@linkplain java.util.Locale locale} to apply during
1234      *         formatting.  If {@code l} is {@code null} then no localization
1235      *         is applied.
1236      *
1237      * @param  format
1238      *         A format string as described in <a
1239      *         href="../util/Formatter.html#syntax">Format string syntax</a>
1240      *
1241      * @param  args
1242      *         Arguments referenced by the format specifiers in the format
1243      *         string.  If there are more arguments than format specifiers, the
1244      *         extra arguments are ignored.  The number of arguments is
1245      *         variable and may be zero.  The maximum number of arguments is
1246      *         limited by the maximum dimension of a Java array as defined by
1247      *         <cite>The Java Virtual Machine Specification</cite>.

1250      *         href="../util/Formatter.html#syntax">conversion</a>.
1251      *
1252      * @throws  java.util.IllegalFormatException
1253      *          If a format string contains an illegal syntax, a format
1254      *          specifier that is incompatible with the given arguments,
1255      *          insufficient arguments given the format string, or other
1256      *          illegal conditions.  For specification of all possible
1257      *          formatting errors, see the <a
1258      *          href="../util/Formatter.html#detail">Details</a> section of the
1259      *          formatter class specification.
1260      *
1261      * @throws  NullPointerException
1262      *          If the {@code format} is {@code null}
1263      *
1264      * @return  This output stream
1265      *
1266      * @since  1.5
1267      */
1268     public PrintStream format(Locale l, String format, Object ... args) {
1269         try {
1270             synchronized (this) {
1271                 ensureOpen();
1272                 if ((formatter == null)
1273                     || (formatter.locale() != l))
1274                     formatter = new Formatter(this, l);
1275                 formatter.format(l, format, args);





1276             }
1277         } catch (InterruptedIOException x) {
1278             Thread.currentThread().interrupt();
1279         } catch (IOException x) {
1280             trouble = true;
1281         }
1282         return this;
1283     }
1284 







1285     /**
1286      * Appends the specified character sequence to this output stream.
1287      *
1288      * <p> An invocation of this method of the form {@code out.append(csq)}
1289      * behaves in exactly the same way as the invocation
1290      *
1291      * <pre>{@code
1292      *     out.print(csq.toString())
1293      * }</pre>
1294      *
1295      * <p> Depending on the specification of {@code toString} for the
1296      * character sequence {@code csq}, the entire sequence may not be
1297      * appended.  For instance, invoking then {@code toString} method of a
1298      * character buffer will return a subsequence whose content depends upon
1299      * the buffer's position and limit.
1300      *
1301      * @param  csq
1302      *         The character sequence to append.  If {@code csq} is
1303      *         {@code null}, then the four characters {@code "null"} are
1304      *         appended to this output stream.

1357      *
1358      * <p> An invocation of this method of the form {@code out.append(c)}
1359      * behaves in exactly the same way as the invocation
1360      *
1361      * <pre>{@code
1362      *     out.print(c)
1363      * }</pre>
1364      *
1365      * @param  c
1366      *         The 16-bit character to append
1367      *
1368      * @return  This output stream
1369      *
1370      * @since  1.5
1371      */
1372     public PrintStream append(char c) {
1373         print(c);
1374         return this;
1375     }
1376 








1377 }

  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);

  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)

 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

 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

 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

 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

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>.

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.

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 }
< prev index next >