【Java基礎知識】IO流--標準輸入輸出流、列印流PrintStream

Windsor90發表於2017-01-21

1 標準輸入流

public static final InputStream in"標準"輸入流。

此流已開啟並準備提供輸入資料。通常,此流對應於鍵盤輸入或者由主機環境或使用者指定的另一個輸入源。
從鍵盤獲取資料的3種方式:
(1)main方法的args接收引數:java param1 param2 Xxx. java
(2)通過使用Scanner類【Jdk 1.5版本後】
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
int x = sc.nextInt()
(3)通過字元緩衝流包裝標準輸入流,來實現
把位元組流轉換成字元流,然後通過字元緩衝流操作。
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
使用案例:通過字元緩衝流來獲取鍵盤錄入的資料。

public class SystemInDemo {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        System.out.println("請輸入一個字串:");
        String line = br.readLine();
        System.out.println("你輸入的字串是:" + line);
        System.out.println("請輸入一個整數:");
        // int i = Integer.parseInt(br.readLine());
        line = br.readLine();
        int i = Integer.parseInt(line);
        System.out.println("你輸入的整數是:" + i);
    }
}

2 標準輸出流

public static final PrintStream out"標準"輸出流。
標準輸出流的例項是列印流【PrintStream】。

此流已開啟並準備接受輸出資料。通常,此流對應於顯示器輸出或者由主機環境或使用者指定的另一個輸出目標。

public class SystemOutDemo {
    public static void main(String[] args) {
        System.out.println("Java");
        // 獲取標準輸出流物件
        PrintStream ps = System.out;
        ps.println("Java");
        ps.println();
    }
}

3 列印流PrintStream、PrintWriter

PrintStream類提供了一系列的print和println()方法,可以實現將基本型別的格式化成字串輸出。
System.out就是PrintStream類的一個例項物件。

3.1 位元組列印流PrintStream

建構函式:

PrintStream(OutputStream out)
PrintStream(OutputStream out,boolean auotflush)
PrintStream(OutputStream out,boolean auotflush, String encoding)

其中autoflush控制在Java中遇到換行符(\n)時是否自動清空緩衝區,encoding是指定編碼方式。println方法與print方法的區別是:println()等於print(“\n”)。Java的PrintStream物件具有多個過載的print和println方法,它們可輸出各種型別(包括Object)的資料。對於基本資料型別的資料,print和println方法會先將它們轉換成字串的形式後再輸出,而不是輸出原始的位元組內容,對於一個非基本資料型別的物件,print和println方法會先呼叫物件的toString方法,然後再輸出toString方法返回的字串。
【PrintStream原始碼部分內容分析:】

public class PrintStream extends FilterOutputStream{

    private final boolean autoFlush;
    private boolean trouble = false;
    private BufferedWriter textOut; //字元緩衝流
    private OutputStreamWriter charOut; //轉換流,作為字元緩衝流的引數

    //建立不帶自動重新整理的列印流。
    public PrintStream(OutputStream out) {
        this(out, false);
    }
    //建立可設定自動重新整理的列印流
    public PrintStream(OutputStream out, boolean autoFlush) {
        this(autoFlush, requireNonNull(out, "Null output stream"));
    }
    //建立給定autoFlush和encoding的列印流
    public PrintStream(OutputStream out, boolean autoFlush, String encoding)
        throws UnsupportedEncodingException{
        this(autoFlush,requireNonNull(out, "Null output stream"),toCharset(encoding));           
    }   

    /* 私有構造 */
    private PrintStream(boolean autoFlush, OutputStream out) {
        super(out);
        this.autoFlush = autoFlush;
        this.charOut = new OutputStreamWriter(this);
        this.textOut = new BufferedWriter(charOut);
    }
    /* 私有構造 */
    private PrintStream(boolean autoFlush, OutputStream out, Charset charset) {
        super(out);
        this.autoFlush = autoFlush;
        this.charOut = new OutputStreamWriter(this, charset);
        this.textOut = new BufferedWriter(charOut);
    }       
    /*檢測IO流物件,確定IO是開啟的狀態 */
    private void ensureOpen() throws IOException {
        if (out == null) throw new IOException("Stream closed");      
    }
    //重新整理IO流
    public void flush() {
        synchronized (this) {
            try {
                ensureOpen();
                out.flush();
            }
            catch (IOException x) {
                trouble = true;
            }
        }
    }
    public void write(int b) {
        try {
            synchronized (this) {
                ensureOpen();
                out.write(b);
                if ((b == '\n') && autoFlush)
                    out.flush();
            }
        }
        catch (InterruptedIOException x) {
            Thread.currentThread().interrupt();
        }
        catch (IOException x) {
            trouble = true;
        }
    }
    public void write(byte buf[], int off, int len) {
        try {
            synchronized (this) {
                ensureOpen();
                out.write(buf, off, len);
                if (autoFlush)
                    out.flush();
            }
        }
        catch (InterruptedIOException x) {
            Thread.currentThread().interrupt();
        }
        catch (IOException x) {
            trouble = true;
        }
    }
    private void write(char buf[]) {
        try {
            synchronized (this) {
                ensureOpen();
                textOut.write(buf);
                textOut.flushBuffer();
                charOut.flushBuffer();
                if (autoFlush) {
                    for (int i = 0; i < buf.length; i++)
                        if (buf[i] == '\n')
                            out.flush();
                }
            }
        }
        catch (InterruptedIOException x) {
            Thread.currentThread().interrupt();
        }
        catch (IOException x) {
            trouble = true;
        }
    }
    private void write(String s) {
        try {
            synchronized (this) {
                ensureOpen();
                textOut.write(s);
                textOut.flushBuffer();
                charOut.flushBuffer();
                if (autoFlush && (s.indexOf('\n') >= 0))
                    out.flush();
            }
        }
        catch (InterruptedIOException x) {
            Thread.currentThread().interrupt();
        }
        catch (IOException x) {
            trouble = true;
        }
    }
    //換行,根據flushBuffer設定,選擇是否自動重新整理
    private void newLine() {
        try {
            synchronized (this) {
                ensureOpen();
                textOut.newLine();
                textOut.flushBuffer();
                charOut.flushBuffer();
                if (autoFlush)
                    out.flush();
            }
        }
        catch (InterruptedIOException x) {
            Thread.currentThread().interrupt();
        }
        catch (IOException x) {
            trouble = true;
        }
    }
    /*以下是print(X x)方法的過載*/
    public void print(boolean b) {
        write(b ? "true" : "false");
    }
    public void print(char c) {
        write(String.valueOf(c));
    }
    public void print(int i) {
        write(String.valueOf(i));
    }
    public void print(long l) {
        write(String.valueOf(l));
    }
    public void print(float f) {
        write(String.valueOf(f));
    }
    public void print(double d) {
        write(String.valueOf(d));
    }
    public void print(char s[]) {
        write(s);
    }
    public void print(String s) {
        if (s == null) {
            s = "null";
        }
        write(s);
    }
    public void print(Object obj) {
        write(String.valueOf(obj));
    }
    //換行
    public void println() {
        newLine();
    }
    /*以下是println(X x)方法的過載*/
    public void println(boolean x) {
        synchronized (this) {
            print(x);
            newLine();
        }
    }
    public void println(char x) {
        synchronized (this) {
            print(x);
            newLine();
        }
    }
    public void println(int x) {
        synchronized (this) {
            print(x);
            newLine();
        }
    }
    public void println(long x) {
        synchronized (this) {
            print(x);
            newLine();
        }
    }
    public void println(float x) {
        synchronized (this) {
            print(x);
            newLine();
        }
    }
    public void println(double x) {
        synchronized (this) {
            print(x);
            newLine();
        }
    }
    public void println(char x[]) {
        synchronized (this) {
            print(x);
            newLine();
        }
    }
    public void println(String x) {
        synchronized (this) {
            print(x);
            newLine();
        }
    }
    public void println(Object x) {
        String s = String.valueOf(x);
        synchronized (this) {
            print(s);
            newLine();
        }
    }
}

3.2 字元列印流PrintWriter

IO包中提供了一個與PrintStream對應的PrintWriter類,PrintWriter即使遇到換行符(\n)也不會自動清空緩衝區,只在設定了autoflush模式下使用了println方法後才自動清空緩衝區。 PrintWriter相對PrintStream最有利的一個地方就是println方法的行為,在Windows的文字換行是”\r\n”, 而Linux下的文字換行是”\n”,如果我們希望程式能夠生成平臺相關的文字換行,而不是在各種平臺下都用”\n”作為文字換行,我們就應該使用PrintWriter的println方法時,PrintWriter的println方法能根據不同的作業系統而生成相應的換行符。
【PrintWriter原始碼部分內容分析:】
位元組流的print(), println()方法的原始碼分析,實際上底層呼叫的是該類成員變數,Writer類物件out的write()方法。out成員變數通過構造初始化。

位元組流的print(), println()方法的原始碼分析,實際上底層呼叫的是
該類成員變數,Writer類物件out的write()方法。out成員變數通過構造初始化。
public class PrintWriter extends Writer{
    protected Writer out;
    private final boolean autoFlush;//是否自動重新整理
    /*
    如果為 true,則每當寫入 byte 陣列、呼叫其中一個 println 方法
    或寫入換行符或位元組 ('\n') 時都會重新整理輸出緩衝區
    */
    private boolean trouble = false;    
    public PrintWriter (Writer out) {
        this(out, false);
    }
    public PrintWriter(Writer out,boolean autoFlush) {                  
        super(out);
        this.out = out;
        this.autoFlush = autoFlush;     
    }
    /*print()可以操作任何型別的資料,下面,
      我們看看原始碼中各種型別資料的處理 */
    public void print(String s) {
        if (s == null) { s = "null"; }
        write(s);
    }
    public void write(String s) {
        write(s, 0, s.length());
    }
    //呼叫字元流out的write方法
    public void write(String s, int off, int len) {
        try {
            synchronized (lock) {
                ensureOpen();
                out.write(s, off, len);
            }
        }
        catch (InterruptedIOException x) {
            Thread.currentThread().interrupt();
        }
        catch (IOException x) {
            trouble = true;
        }
    }
    /*檢查out,確保流是開啟的*/
    private void ensureOpen() throws IOException {
        if (out == null)
            throw new IOException("Stream closed");
    }   
    /*
     print()可以操作,boolean,int,long, float, double,chae[]
     Object等型別
    */
    public void print(boolean b) {
        write(b ? "true" : "false");
    }
    public void print(char c) {
        write(c);
    }
    public void print(int i) {
        write(String.valueOf(i));
    }   
    public void print(long l) {
        write(String.valueOf(l));
    }   
    public void print(float f) {
        write(String.valueOf(f));
    }   
    public void print(double d) {
        write(String.valueOf(d));
    }   
    public void print(char s[]) {
        write(s);
    }
    public void print(Object obj) {
        write(String.valueOf(obj));
    }
/*println()換行,原始碼分析:如果autoFlush為true
則呼叫println()還啟用了自動重新整理的功能。
*/
    public void println() {
        newLine();
    }
    private void newLine() {
        try {
            synchronized (lock) {
                ensureOpen();
                out.write(lineSeparator);
                if (autoFlush)
                    out.flush();
            }
        }
        catch (InterruptedIOException x) {
            Thread.currentThread().interrupt();
        }
        catch (IOException x) {
            trouble = true;
        }
    }   
}

相關文章