package java.io;

class PrintStream extends FilterOutputStream {
	private final boolean autoFlush;
	private boolean trouble = false;
	
	/**
     * Track both the text- and character-output streams, so that their buffers
     * can be flushed without flushing the entire stream.
     */
	private BufferedWriter textOut; // 缓冲字符输出流
    private OutputStreamWriter charOut; // 字符-->字节 转换流
	
	/**
     * Creates a new print stream.
     *
     * @param  out        The output stream to which values and objects will be
     *                    printed
     * @param  autoFlush  A boolean; if true, the output buffer will be flushed
     *                    whenever a byte array is written, one of the
     *                    <code>println</code> methods is invoked, or a newline
     *                    character or byte (<code>'\n'</code>) is written
     *
     * @see java.io.PrintWriter#PrintWriter(java.io.OutputStream, boolean)
     */
	/*
	 * 如果是真,当有字节数组被写入时输出缓冲区就会被刷新,println()方法被调用,或者一个新行字符或'\n'被写入时
	 */
    public PrintStream(OutputStream out, boolean autoFlush) {
        this(autoFlush, requireNonNull(out, "Null output stream"));
    }
	
    /**
     * Prints an array of characters.  The characters are converted into bytes
     * according to the platform's default character encoding, and these bytes
     * are written in exactly the manner of the
     * <code>{@link #write(int)}</code> method.
     *
     * @params  The array of chars to be printed
     *
     * @throws  NullPointerException  If <code>s</code> is <code>null</code>
     */
	/*
	 * 打印一个字符数组。
	 * 字符通过平台默认的编码集被转换成字节,以write()方法的方式恰当地写出这些字节。
	 */
    public void print(char s[]) {
        write(s);
    }
	
	/** Check to make sure that the stream has not been closed */
    private void ensureOpen() throws IOException {
        if (out == null)
            throw new IOException("Stream closed");
    }
	
	/*
     * The following private methods on the text- and character-output streams
     * always flush the stream buffers, so that writes to the underlying byte
     * stream occur as promptly as with the original PrintStream.
     */
	/*
	 * 下面的私有方法经常用于字符输出流强制刷新流缓冲区,以便立即写到基础的字节流当有原始打印流出现
	 */

    private void write(char buf[]) {
        try {
            synchronized (this) {
                ensureOpen(); // 确保流没有被关闭
				/*
				 * in Writer
				 * Writes an array of characters.
				 */
                textOut.write(buf); // 写入字符数组
				/*
				 * in BufferedWriter
				 * Flushes the output buffer to the underlying character stream, without
				 * flushing the stream itself.  This method is non-private only so that it
				 * may be invoked by PrintStream.
				 */
				/*
				 * 刷新输出缓冲区到基础输出流,而不刷新流本身。
				 * 这个方法没有被私有化可能会被PrintStream调用。
				 */
                textOut.flushBuffer(); // 缓冲字符输出流刷新缓冲区
				/*
				 * in OutputStreamWriter 
				 * Flushes the output buffer to the underlying byte stream, without flushing
				 * the byte stream itself.  This method is non-private only so that it may
				 * be invoked by PrintStream.
				 */
                charOut.flushBuffer(); // 转换流刷新缓冲区
                if (autoFlush) {
                    for (int i = 0; i < buf.length; i++)
                        if (buf[i] == '\n')
							/*
							 * in superclass FilterOutputStream
							 * The underlying output stream to be filtered.
							 * 要过滤的基础输出流
							 *
							 * protected OutputStream out;	
							 */
							/*
							 * in OutputStream
							 * Flushes this output stream and forces any buffered output bytes
							 * to be written out. The general contract of <code>flush</code> is
							 * that calling it is an indication that, if any bytes previously
							 * written have been buffered by the implementation of the output
							 * stream, such bytes should immediately be written to their
							 * intended destination.
							 * <p>
							 * If the intended destination of this stream is an abstraction provided by
							 * the underlying operating system, for example a file, then flushing the
							 * stream guarantees only that bytes previously written to the stream are
							 * passed to the operating system for writing; it does not guarantee that
							 * they are actually written to a physical device such as a disk drive.
							 * <p>
							 * The <code>flush</code> method of <code>OutputStream</code> does nothing.
							 *
							 * @exception  IOException  if an I/O error occurs.
							 */
							/*
							 * 刷新此输出流并强制写出所有缓冲的输出字节。
							 * flush 的常规协定是:如果此输出流的实现已经缓冲了以前写入的任何字节,
							 * 则调用此方法指示应将这些字节立即写入它们预期的目标。
							 * 如果此流的预期目标是由基础操作系统提供的一个抽象(如一个文件),
							 * 则刷新此流只能保证将以前写入到流的字节传递给操作系统进行写入,
							 * 但不保证能将这些字节实际写入到物理设备(如磁盘驱动器)。 
							 * 
							 * OutputStream 的 flush 方法不执行任何操作。 
							 * 如果发生 I/O 错误抛出 IO 异常。
							 */
                            out.flush();
                }
            }
        }
        catch (InterruptedIOException x) {
            Thread.currentThread().interrupt();
        }
        catch (IOException x) {
            trouble = true;
        }
    }
}