天天看點

Java之IO流總結

  序言-

  第一次寫部落格,雖然工作1年了,一直沒想起來去分享什麼,後來聽同僚說,沒事喜歡去寫寫部落格,我覺得,作為一個程式員,應該具備分享精神,是以覺得從基礎開始,給剛接觸Java的同學,一點點小小i的幫助,也算給自己溫故而知新的機會。

  下面開始我們的Java學習之旅吧。

    IO流

·Java流式輸入/輸出原理

·Java流類的分類

·輸入/輸出流類

·常見的節點流和處理流

·檔案流

·緩沖流

·轉換流

·資料流

·Print流

·Object流

①Java流式輸入/輸出原理

        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

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

        //讀取一系列字元并存儲到一個數組buffer

        //傳回實際讀取的字元數,如果讀取器前已到輸入流的末尾傳回-1

        //讀取length個字元

        //并存儲到一個字元數組buffer,從length位置開始

        //傳回實際讀取的字元數,如果讀取前已到輸入流的末尾傳回-1

        //length - 要讀取的最大字元數。

        //跳過n個字元不讀,傳回實際跳過的位元組數

             |----BufferedWriter(處理流)

             |----CharArrayWriter(節點流)    

             |----OutputStreamReader(處理流)-----FileWriter(節點流)

             Writer -|----FilterWriter(處理流)

             |----PipedWriter(節點流)

             |----StringWriter(節點流)

Writer的基本方法

        //向輸出流中寫入一個字元資料,該位元組資料為參數b的低8位

        //将一個字元類型的數組中的資料寫入輸出流

    ·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

③輸入/輸出流

    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{

            //????????

        //????????

                int num = 0;

    發現出現?????,問題是漢字是一個字元(兩個位元組),用的是位元組流,一個位元組一個位元組讀取,

所有中文翻譯不出來,改為Reader可以

    從程式到檔案

    ·使用FileOutputStream

import java.io.FileOutputStream;

        FileOutputStream fot = null;

            fot = new FileOutputStream("C://Users//woshishabi//Desktop//test.txt");

                    fot.write(b);

                fot.close();

    桌面上多了一個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.FileReader;

import java.io.FileWriter;

            //從檔案寫入資料

            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

import java.io.OutputStreamWriter;

            //将輸出位元組流轉換為字元流

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

                // TODO Auto-generated catch block

                e.printStackTrace();

範例:InputStreamReader

import java.io.InputStreamReader;

        //從鍵盤讀取資料

        InputStreamReader isr = new InputStreamReader(System.in);

        //字元輸入緩沖流

        BufferedReader br = new BufferedReader(isr);

        String s = null;

            //讀取一行字元

            s = br.readLine();

            while(s != null){

            if(s.equalsIgnoreCase("exit")){     //将一個字元串與另一個字元串比較,不考慮大小寫

                break;    

            //将小寫轉換為大寫

                System.out.println(s.toUpperCase());

                s = br.readLine();

         catch (IOException e) {

⑧資料流----DataInputStream...

    ·DataInputStream 和 DataOutputStream 分别繼承了InputStream 和 OutputStream,屬于處理流,

需要分别套接在InputStream 和 OutputStream類型的節點流觞

    ·DataInputStream 和 DataOutputStream 提供了可以存取與機器無關的Java原始資料類型(int、double等)

的方法

    ·DataInputStream 和 DataOutputStream 的構造方法為:

        ·DataInputStream(InputStream in)

        ·DataOutputStream(OutputStream out)

範例:使用DataInputStream 和 DataOutputStream

import java.io.ByteArrayInputStream;

import java.io.ByteArrayOutputStream;

import java.io.DataInputStream;

import java.io.DataOutputStream;

        //一個位元組數組輸出流

        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        //在位元組數組輸出流上套接一個資料流,能傳遞基本資料類型

        DataOutputStream dos = new DataOutputStream(baos);

            //向位元組數組寫入一個随機數

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

⑨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

import java.io.PrintStream;

        PrintStream ps = null;

            //檔案位元組輸出流

            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 + ",");

範例:PrintWriter

import java.io.PrintWriter;

import java.util.Date;

        //從鍵盤輸入,位元組轉字元的轉換流上套接緩沖流

        BufferedReader bis = new BufferedReader(new InputStreamReader(System.in));

            //輸出流,輸出到檔案,不覆寫

            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中輸出

                //在目标檔案裡面輸出資料

                pw.println("------");

                pw.println(s.toLowerCase());

                pw.flush();

            //在目标檔案中輸出日期

            pw.println("-----"+ new Date() + "------");

            pw.flush();

            pw.close();

⑩Object流

    ·直接将Object寫入或讀出

        ·transient關鍵字(透明的):修飾屬性, transient int k  = 15;   輸出結果k = 0;在序列化的時候不考慮,不寫入硬碟

        ·serializable接口:(标記性接口,裡面什麼都沒有)

        ·extemalizable接口:

    注意:如果需要使用對象流,必須實作serializable接口

範例:

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import java.io.Serializable;

        T t = new T();

        t.k = 40;

            //檔案輸出流,

            //在檔案輸出流上套接一個對象輸出流,從程式傳遞一個對象到目标檔案中

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

        catch (IOException e) {

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