Java之IO流總結

一杯涼茶發表於2016-03-27

    IO流
·Java流式輸入/輸出原理
·Java流類的分類
·輸入/輸出流類
·常見的節點流和處理流
·檔案流
·緩衝流
·轉換流
·資料流
·Print流
·Object流

①Java流式輸入/輸出原理
    
        00101...-->
    檔案 ------------------ 程式

        <-- ...00101
    檔案 ------------------ 程式
    
           00101...-->
    網路連線 ------------------ 程式

        00101...-->
    程式 ------------------ 程式

         00101...-->  “Hello”
    檔案 -----------============== 程式 (從0101等轉換為字元,一層包一層)

②流的分類
    java.io包中
        ·按資料流的方向不同可以分為輸入流、輸出流
        ·按處理資料單位不同可以分為位元組流、字元流
        ·按照功能不同可以分為節點流、處理流

    所有流型別位於包java.io內都分別繼承以下四種抽象流型別

            位元組流        字元流
    ------------------------------------------
    輸入流          InputStream      Reader
    輸出流          OutputSteam      Writer


        位元組流(8bit)

             |----FileInputStream(節點流)
             |
             |----PipedInputStream(節點流)     |---LineNumberInputStream(處理流)
             |                          |       
             |----FilterInputStream(處理流)-------|---DataInputStream(處理流)
             |                     |
    InputStream -|----ByteArrayInputStream(節點流)    |---BufferedInputStream(處理流)
             |                     |---PushbackInputStream(處理流)        
             |----SequenceInputStream(處理流)
             |
             |----StringBufferInputStream(節點流)
             |
             |----ObjectInputStream(處理流)

InputStream的基本方法
        //讀取一個位元組並以整數的形式返回(0-255)
        //如果返回-1已到輸入流的末尾
    ·int read() throws IOExcetion

        //讀取一系列位元組並儲存到一個陣列buffer
        //返回實際讀取的位元組數,如果讀取器前已到輸入流的末尾返回-1
    ·int read(byre[] buffer) throws IOExcetion

        //讀取length個位元組
        //並儲存到一個位元組陣列buffer,從length位置開始
        //返回實際讀取的位元組數,如果讀取前已到輸入流的末尾返回-1
        //buffer - 讀入資料的緩衝區。
        //offset - 陣列 buffer 中將寫入資料的初始偏移量。
        //length - 要讀取的最大位元組數。
    ·int read(byte[] buffer, int offset, int length) throws IOExcetion

        //關閉流釋放記憶體資源
    ·void close() throws IOExcetion

        //跳過n個位元組不讀,返回實際跳過的位元組數
    ·long skip(long n) throws IOExcetion


        位元組流(8bit)

             |----FileOutputStream(節點流)
             |
             |----PipedOutputStream(節點流)    
             |                          |       
             |----FilterOutputStream(處理流)-----|---DataOutputStream(處理流)
             |                     |
       OutputStream -|----ByteArrayOutputStream(節點流)  |---BufferedOutputStream(處理流)
             |                     |---PrintStream(處理流)        
             |
             |----ObjectOutputStream(處理流)

OutputStream的基本方法
        //向輸出流中寫入一個位元組資料,該位元組資料為引數b的低8位
    ·void write(int b) throws IOException
    
        //將一個位元組型別的陣列中的資料寫入輸出流
    ·void write(byre[] b) throws IOException

        //將一個位元組型別的陣列中的從指定位置(off)開始的len個位元組寫入到輸出流
    ·void write(byre[] b, int off, int len) throws IOException

        //關閉流釋放記憶體資源
    ·void close() throws IOException

        //將輸出流中緩衝的資料全部寫出到目的地
    ·void flush() throws IOException

    注意:先flush,在close



        字元流(16bit)

             |----BufferedReader(節點流)----LineNumberReader(處理流)
             |
             |----CharArrayReader(處理流)    
             |                              
             |----InputStreamReader(處理流)-----FileReader(節點流)
             |                    
             Reader -|----FilterReader(處理流)----PushbackReader(處理流)
             |                         
             |
             |----PipedReader(節點流)
             |
             |----StringReader(節點流)


Reader的基本方法
        //讀取一個字元並以整數的形式返回(0-255)
        //如果返回-1已到輸入流的末尾
    ·int read() throws IOExcetion

        //讀取一系列字元並儲存到一個陣列buffer
        //返回實際讀取的字元數,如果讀取器前已到輸入流的末尾返回-1
    ·int read(byre[] buffer) throws IOExcetion

        //讀取length個字元
        //並儲存到一個字元陣列buffer,從length位置開始
        //返回實際讀取的字元數,如果讀取前已到輸入流的末尾返回-1
        //buffer - 讀入資料的緩衝區。
        //offset - 陣列 buffer 中將寫入資料的初始偏移量。
        //length - 要讀取的最大字元數。
    ·int read(byte[] buffer, int offset, int length) throws IOExcetion

        //關閉流釋放記憶體資源
    ·void close() throws IOExcetion

        //跳過n個字元不讀,返回實際跳過的位元組數
    ·long skip(long n) throws IOExcetion


        字元流(16bit)

             |----BufferedWriter(處理流)
             |
             |----CharArrayWriter(節點流)    
             |                              
             |----OutputStreamReader(處理流)-----FileWriter(節點流)
             |                    
             Writer -|----FilterWriter(處理流)
             |                         
             |
             |----PipedWriter(節點流)
             |
             |----StringWriter(節點流)

Writer的基本方法
        //向輸出流中寫入一個字元資料,該位元組資料為引數b的低8位
    ·void write(int b) throws IOException
    
        //將一個字元型別的陣列中的資料寫入輸出流
    ·void write(char[] cbuf) throws IOException

        //將一個字元型別的陣列中的從指定位置(off)開始的len個字元寫入到輸出流
    ·void write(char[] cbuf, int off, int len) throws IOException

        //將一個字串中的字元寫入到輸出流
    ·void write(String string) throws IOException

        //將一個字串從offset開始的length個字元寫入到輸出流
    ·coid write(String string, int offset, int length) throws IOException

        //關閉流釋放記憶體資源
    ·void close() throws IOException

        //將輸出流中緩衝的資料全部寫出到目的地
    ·void flush() throws IOException


③輸入/輸出流
    1、輸出流跟輸入流
    一切以程式為中心
        ·從檔案到程式為輸入流
        ·從程式到檔案為輸出流
    2、位元組流和字元流
        ·位元組(8bit)
        ·字元(16bit)
        ·一個字元等於2個位元組
    3、節點流和處理流
        ·處理流是包在節點流的一層“管道”

④常見的節點流和處理流
    ·節點流為可以從一個特定的資料來源(節點)讀寫資料(如:檔案,記憶體)
            節點流
        資料來源 -------------------- 程式
        
    ·處理流是連線在已存在的流(節點流或處理流)之上,通過對資料的處理為程式提供更為強大的讀寫功能

            -->
        資料來源 -------======== 程式
            
            <--
        程式 ============-------- 資料來源

⑤節點流----檔案流
    字元流            位元組流
---------------------------------------
輸入流    FileReader    FileInputStream
輸出流    FileWriter    FileOutputStream

訪問檔案
    從檔案到程式,輸入流
    ·使用FileInputStream

        public class Login{
    public static void main(String[] args){
        int b = 0;
        FileInputStream fis = null;
        try {
            //連線管道
            fis = new FileInputStream("G://Java2014Project//JavaDemo1//src//Demo01/Login.java");
        } catch (FileNotFoundException e) {
            System.out.println("error");
        }
        //讀取資料
            try {
                while((b = fis.read())!= -1){
                    System.out.print((char)(b));
                    
                }
                fis.close();
            } catch (IOException e) {
                System.out.println("error");
            }
        
    }
}
    顯示結果
    package Demo01;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class Login{
    public static void main(String[] args){
        int b = 0;
        FileInputStream fis = null;
        try {
            //????????
            fis = new FileInputStream("G://Java2014Project//JavaDemo1//src//Demo01/Login.java");
        } catch (FileNotFoundException e) {
            System.out.println("error");
        }
        //????????
            try {
                int num = 0;
                while((b = fis.read())!= -1){
                    System.out.print((char)(b));
                }
                fis.close();
            } catch (IOException e) {
                System.out.println("error");
            }
        
    }
}

    發現出現?????,問題是漢字是一個字元(兩個位元組),用的是位元組流,一個位元組一個位元組讀取,
所有中文翻譯不出來,改為Reader可以
    
    從程式到檔案
    ·使用FileOutputStream
    package Demo01;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class Login{
    public static void main(String[] args){
        int b = 0;
        FileInputStream fis = null;
        FileOutputStream fot = null;
        try {
            //連線管道
            fis = new FileInputStream("G://Java2014Project//JavaDemo1//src//Demo01/Login.java");
            fot = new FileOutputStream("C://Users//woshishabi//Desktop//test.txt");
        } catch (FileNotFoundException e) {
            System.out.println("error");
        }
        //讀取資料
            try {
                while((b = fis.read())!= -1){
                    fot.write(b);
                }
                fis.close();
                fot.close();
            } catch (IOException e) {
                System.out.println("error");
            }
        
    }
}

    桌面上多了一個Test.txt文字,


    ·使用FileReader:字元輸入流,從檔案到程式
        ......
    ·使用FileWriter:字元輸出流,從程式到檔案
        ......

⑥處理流----緩衝流
    ·緩衝流要“套接”在相應的節點流之上,對讀寫的資料提供了緩衝的功能,提高了讀寫的效率,
同時增加了一些新的方法
    ·J2SDK提供了四種快取流,其常用的構造方法為:
            //字元輸入緩衝流
        BufferedReader(Reader in)
        BufferedReader(Reader in, int sz) //sz為自定義快取區的大小    
            
            //字元輸出緩衝流
        BufferedWriter(Writer out)
        BufferedWriter(Writer out,int sz)
        
            //位元組輸入緩衝流
        BufferedInputStream(InputStream in)
        BufferedInputStream(InputStream in, int size)
    
            //位元組輸出緩衝流
        BufferedOutputStream(OutputStream out)
        BufferedOutputStream(OutputStream out, int size)

    ·緩衝輸入流支援其父類的mark和reset方法    mark:直接從多少個字元開始讀取  reset:回到剛才標記的點
    ·bufferedReader提供了readline方法用於讀取一行字串(以\r或\n分隔)
    ·bufferedWriter提供了newLine用於寫入一個行分隔符
    ·對於輸出的緩衝流,寫出的資料會現在記憶體中快取,使用flush方法將會使記憶體中的資料立刻寫出

bufferedReader和bufferedWriter使用

package Demo01;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class Login{
    public static void main(String[] args){
        try {
            //從檔案寫入資料
            BufferedReader br  = new BufferedReader(new FileReader("G://Java2014Project//JavaDemo1//src//Demo01//Login.java"));
            BufferedWriter bw = new BufferedWriter(new FileWriter("C://Users//woshishabi//Desktop//Test.txt"));
            //從檔案讀取資料
            String s = null;
            while((s = br.readLine()) != null){
                System.out.println(s);
                bw.write(s);
                bw.newLine();
            }
            bw.flush();
            br.close();
            bw.close();
        }
            catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    
    }
}


⑦處理流----轉換流
    ·InputStreamReader和OutputStreamWriter用與位元組資料到字元資料之間的轉換
    ·InputStreamReader需要和InputStream“套接”
    ·OutputStream需要和OutputStream“套接”
    ·轉換流在構造時可以指定其編碼集合,例如
        InputStream isr = new InputStreamReader(System.in, "ISO8859_1");

範例:OutputStreamWriter

    package Demo01;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;

public class Login{
    public static void main(String[] args){
        try {
            //將輸出位元組流轉換為字元流
            OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("C://Users//woshishabi//Desktop//Test.txt"));
            //向檔案中輸入字串
            osw.write("sdfjaksldjflskdjflaskdjfsakjdf");
            //讀取字元編碼
            System.out.println(osw.getEncoding());
            osw.close();
            //在文字後面新增字串,不覆蓋,則true,否則寫false, 後面可以自定義編碼
            osw = new OutputStreamWriter(new FileOutputStream("C://Users//woshishabi//Desktop//Test.txt", true), "UTF-8");
            osw.write("qwqeqweqweqeq");
            System.out.println(osw.getEncoding());
            osw.close();
        }
            catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
        }
    }

範例:InputStreamReader

    package Demo01;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

public class Login{
    public static void main(String[] args){
        //從鍵盤讀取資料
        InputStreamReader isr = new InputStreamReader(System.in);
        //字元輸入緩衝流
        BufferedReader br = new BufferedReader(isr);
        String s = null;
        try {
            //讀取一行字元
            s = br.readLine();
            while(s != null){
            if(s.equalsIgnoreCase("exit")){     //將一個字串與另一個字串比較,不考慮大小寫
                break;    
            }
            //將小寫轉換為大寫
                System.out.println(s.toUpperCase());
                s = br.readLine();
            }
            br.close();
            
            }
         catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }
}


⑧資料流----DataInputStream...
    ·DataInputStream 和 DataOutputStream 分別繼承了InputStream 和 OutputStream,屬於處理流,
需要分別套接在InputStream 和 OutputStream型別的節點流觴
    ·DataInputStream 和 DataOutputStream 提供了可以存取與機器無關的Java原始資料型別(int、double等)
的方法
    ·DataInputStream 和 DataOutputStream 的構造方法為:
        ·DataInputStream(InputStream in)
        ·DataOutputStream(OutputStream out)
    
範例:使用DataInputStream 和 DataOutputStream
package Demo01;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

public class Login{
    public static void main(String[] args){
        //一個位元組陣列輸出流
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        //在位元組陣列輸出流上套接一個資料流,能傳遞基本資料型別
        DataOutputStream dos = new DataOutputStream(baos);
        try {
            //向位元組陣列寫入一個隨機數
            dos.writeDouble(Math.random());
            dos.writeBoolean(true);
            //建立一個位元組陣列輸入流
            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
            //輸出位元組陣列中有多少個位元組
            System.out.println(bais.available());
            //將處理流包在位元組陣列輸入流上,輸出基本資料
            DataInputStream dis = new DataInputStream(bais);
            //輸出double,先輸入的先輸出
            System.out.println(dis.readDouble());
            //輸出boolean
            System.out.println(dis.readBoolean());
            dos.close();
            dis.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

    
⑨print流    PrintStream主要操作byte流,而PrintWriter用來操作字元流
    ·PrintWriter 和 PrintStream都屬於輸出流,分別針對與字元和位元組
    ·PrintWriter 和 PrintStream提供了過載的print
    ·Println方法用於多種資料型別的輸出
    ·PrintWriter 和 PrintStream的輸出操作不會丟擲異常,使用者通過檢測錯誤狀態獲取錯誤資訊
    ·PrintWriter 和 PrintStream有自動flush功能
構造方法:
    ·PrintWriter(Writer out)
    ·PrintWriter(Writer out,boolean autoFlush)
    ·PrintWriter(OutputStream out, boolean autoFlush)
    ·PrintStream(OutputStream out)
    ·PrintStream(OutputStream out, boolean autoFlush)

範例:PrintStream
package Demo01;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintStream;

public class Login{
    public static void main(String[] args){
        PrintStream ps = null;
        try {
            //檔案位元組輸出流
            FileOutputStream fos = new FileOutputStream("C://Users//woshishabi//Desktop//Test.txt");
            //輸出流
            ps = new PrintStream(fos);
            if(ps != null){
                //使system.out指向了檔案Test.txt
                System.setOut(ps);
            }
            for (int i = 0; i < 100; i++) {
                System.out.print(i + ",");
            }

        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}


範例:PrintWriter

    package Demo01;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.Date;

public class Login{
    public static void main(String[] args){
        String s = null;
        //從鍵盤輸入,位元組轉字元的轉換流上套接緩衝流
        BufferedReader bis = new BufferedReader(new InputStreamReader(System.in));
        try {
            //輸出流,輸出到檔案,不覆蓋
            FileWriter fw = new FileWriter("C://Users//woshishabi//Desktop//Test.txt",true);
            //輸出流,套接在檔案輸出流上
            PrintWriter pw = new PrintWriter(fw);
            //接收鍵盤輸入的一行資料,
            while((s = bis.readLine()) != null){
                //判斷是否為exit,是則結束while
                if(s.equalsIgnoreCase("exit"))break;
                //小寫轉大寫,在dos中輸出
                System.out.println(s.toUpperCase());
                //在目標檔案裡面輸出資料
                pw.println("------");
                pw.println(s.toLowerCase());
                pw.flush();
            }
            //在目標檔案中輸出日期
            pw.println("-----"+ new Date() + "------");
            pw.flush();
            pw.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}


⑩Object流
    ·直接將Object寫入或讀出
        ·transient關鍵字(透明的):修飾屬性, transient int k  = 15;   輸出結果k = 0;在序列化的時候不考慮,不寫入硬碟
        ·serializable介面:(標記性介面,裡面什麼都沒有)
        ·extemalizable介面:
    注意:如果需要使用物件流,必須實現serializable介面

範例:
    package Demo01;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.Serializable;
import java.util.Date;

public class Login{
    public static void main(String[] args){
        T t = new T();
        t.k = 40;
        try {
            //檔案輸出流,
            FileOutputStream fos = new FileOutputStream("C://Users//woshishabi//Desktop//Test.txt");
            //在檔案輸出流上套接一個物件輸出流,從程式傳遞一個物件到目標檔案中
            ObjectOutputStream  oos = new ObjectOutputStream(fos);
            //寫入物件
            oos.writeObject(t);
            //檔案輸入流,鎖定目標檔案
            FileInputStream fis = new FileInputStream("C://Users//woshishabi//Desktop//Test.txt");
            //在檔案輸入流上套接一個物件輸入流,從目標檔案中取出物件的通道
            ObjectInputStream ois = new ObjectInputStream(fis);

            //取出物件
            T t1 = (T) ois.readObject();
            //列印到螢幕上
            System.out.println(t1.i + " " + t1.j + " " + t1.k + " " + t1.z);
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}

class T implements Serializable{
    int i = 1;
    int j = 2;
    double z = 9.0;
    int k = 14;

}




總結:
    ·InputStream/OutputStream

    ·Reader/Writer

    ·FileInputStream/FileoutputStream

    ·FileReader/FileWriter

    ·BufferedInputStream/BufferedOutoutStream

    ·BufferedTeader/BufferedWriter

    ·ByteArrayInputStream/ByteArrayOutputStream

    ·InputStreamReader/OutputStreamWriter

    ·DataInputStream/DataOutputStream

    ·PrintStream/PrintWriter

    ·ObjectInputStream/ObjectOutputStream