1. 程式人生 > >IO流歸納總結

IO流歸納總結

IO流的分類:

IO流常見類

IO流小結(掌握)
IO流
    |--位元組流
        |--位元組輸入流
            InputStream
                int read():一次讀取一個位元組
                int read(byte[] bys):一次讀取一個位元組陣列

                |--FileInputStream
                |--BufferedInputStream
        |--位元組輸出流
            OutputStream
                void write(int by):一次寫一個位元組
                void write(byte[] bys,int index,int len):一次寫一個位元組陣列的一部分

                |--FileOutputStream
                |--BufferedOutputStream
    |--字元流
        |--字元輸入流
            Reader
                int read():一次讀取一個字元
                int read(char[] chs):一次讀取一個字元陣列

                |--InputStreamReader
                    |--FileReader
                |--BufferedReader
                    String readLine():一次讀取一個字串
        |--字元輸出流
            Writer
                void write(int ch):一次寫一個字元
                void write(char[] chs,int index,int len):一次寫一個字元陣列的一部分

                |--OutputStreamWriter
                    |--FileWriter
                |--BufferedWriter
                    void newLine():寫一個換行符

                    void write(String line):一次寫一個字串

流向:
* 輸入流 讀取資料
* 輸出流 寫出資料
資料型別:
* 位元組流
* 位元組輸入流 讀取資料 InputStream
* 位元組輸出流 寫出資料 OutputStream
* 字元流
* 字元輸入流 讀取資料 Reader
* 字元輸出流 寫出資料 Writer

FileOutputStream

OutputStream 是一個抽象類,無法直接使用,必須找到實現其功能的子類,就是FileOutputStream

位元組輸出流操作步驟:

  • A:建立位元組輸出流物件
  • B:寫資料
  • C:釋放資源

例1:寫入全部的位元組流

public class FileOutputStreamDemo {
    public static void main(String[] args) throws IOException {
        // 建立位元組輸出流物件
        // FileOutputStream(File file)
        // File file = new File("fos.txt");
        // FileOutputStream fos = new FileOutputStream(file);
// FileOutputStream(String name) /* * 建立位元組輸出流物件了做了幾件事情: * A:呼叫系統功能去建立檔案 * B:建立fos物件 * C:把fos物件指向這個檔案 */ FileOutputStream fos = new FileOutputStream("fos.txt"); //寫資料 fos.write("hello,IO".getBytes()); fos.write("java".getBytes()); //這裡寫入了兩個資料,但是沒有實現換行,怎麼樣實現換行呢?詳情見例3 //釋放資源 //關閉此檔案輸出流並釋放與此流有關的所有系統資源。 fos.close(); /* * 為什麼一定要close()呢? * A:讓流物件變成垃圾,這樣就可以被垃圾回收器回收了 * B:通知系統去釋放跟該檔案相關的資源 */ //java.io.IOException: Stream Closed //fos.write("java".getBytes()); } }

例2:寫入位元組流的一部分資料

三個方法:
* public void write(int b):寫一個位元組
* public void write(byte[] b):寫一個位元組陣列
* public void write(byte[] b,int off,int len):寫一個位元組陣列的一部分

public class FileOutputStreamDemo2 {
    public static void main(String[] args) throws IOException {
        // 建立位元組輸出流物件
        // OutputStream os = new FileOutputStream("fos2.txt"); // 多型
        FileOutputStream fos = new FileOutputStream("fos2.txt");

        // 呼叫write()方法
        //fos.write(97); //97 -- 底層二進位制資料    -- 通過記事本開啟 -- 找97對應的字元值 -- a
        // fos.write(57);
        // fos.write(55);

        //public void write(byte[] b):寫一個位元組陣列
        byte[] bys={97,98,99,100,101};
        fos.write(bys);

        //public void write(byte[] b,int off,int len):寫一個位元組陣列的一部分
        fos.write(bys,1,3);

        //釋放資源
        fos.close();
    }
}

例3:實現多條資料換行

public class FileOutputStreamDemo3 {
    public static void main(String[] args) throws IOException {
        // 建立位元組輸出流物件
        // FileOutputStream fos = new FileOutputStream("fos3.txt");
        // 建立一個向具有指定 name 的檔案中寫入資料的輸出檔案流。
        //如果第二個引數為 true,則將位元組寫入檔案末尾處,而不是寫入檔案開始處。
        FileOutputStream fos = new FileOutputStream("fos3.txt", true);

        // 寫資料
        for (int x = 0; x < 10; x++) {
            fos.write(("hello" + x).getBytes());
            fos.write("\r\n".getBytes());
        }

        // 釋放資源
        fos.close();
    }
}

例4:加入異常處理的outputStream操作

public class FileOutputStreamDemo4 {
    public static void main(String[] args) {        
        // 改進版
        // 為了在finally裡面能夠看到該物件就必須定義到外面,為了訪問不出問題,還必須給初始化值
        FileOutputStream fos = null;
        try {
            // fos = new FileOutputStream("z:\\fos4.txt");
            fos = new FileOutputStream("fos4.txt");
            fos.write("java".getBytes());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 如果fos不是null,才需要close()
            if (fos != null) {
                // 為了保證close()一定會執行,就放到這裡了
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

FileInputStream

操作步驟

位元組輸入流操作步驟:
     A:建立位元組輸入流物件
     B:呼叫read()方法讀取資料,並把資料顯示在控制檯
     C:釋放資源
讀取方式:
     A:int read():一次讀取一個位元組
     B:int read(byte[] b):一次讀取一個位元組陣列

例1:一次粗去一個位元組

public class FileInputStreamDemo {
    public static void main(String[] args) throws IOException {
        // FileInputStream(String name)
        // FileInputStream fis = new FileInputStream("fis.txt");
        FileInputStream fis = new FileInputStream("FileOutputStreamDemo.java");
        int by = 0;
        // 讀取,賦值,判斷
        while ((by = fis.read()) != -1) {
            System.out.print((char) by);
        }

        // 釋放資源
        fis.close();
    }
}

例2:一次讀取1024個位元組陣列

public class FileInputStreamDemo2 {
    public static void main(String[] args) throws IOException {
        // 建立位元組輸入流物件
        // FileInputStream fis = new FileInputStream("fis2.txt");
        FileInputStream fis = new FileInputStream("FileOutputStreamDemo.java");
            // 陣列的長度一般是1024或者1024的整數倍
        byte[] bys = new byte[1024];
        int len = 0;
        while ((len = fis.read(bys)) != -1) {
            System.out.print(new String(bys, 0, len));
        }

        // 釋放資源
        fis.close();
    }
}

BufferedOutputStream

概述:
    BufferedInputStream 的作用其實和fileInputStream的作用類似,但是BufferedInputStream 有緩衝區,就是說你在讀取檔案的時候不需要讀取一次就訪問一次硬碟,二次讀取很多次,然後把讀取的資料一次性快取在cpu中,這樣訪問的速度就會快很多了;

例1:

 * 為什麼不傳遞一個具體的檔案或者檔案路徑,而是傳遞一個OutputStream物件呢?
 * 原因很簡單,位元組緩衝區流僅僅提供緩衝區,為高效而設計的。但是呢,真正的讀寫操作還得靠基本的流物件實現。
 */
public class BufferedOutputStreamDemo {
    public static void main(String[] args) throws IOException {
        // BufferedOutputStream(OutputStream out)
        // FileOutputStream fos = new FileOutputStream("bos.txt");
        // BufferedOutputStream bos = new BufferedOutputStream(fos);
        // 簡單寫法
        BufferedOutputStream bos = new BufferedOutputStream(
                new FileOutputStream("bos.txt"));

        // 寫資料
        bos.write("hello".getBytes());

        // 釋放資源
        bos.close();
    }
}

BufferedInputStream

例1:
/*
 * 注意:雖然我們有兩種方式可以讀取,但是,請注意,這兩種方式針對同一個物件在一個程式碼中只能使用一個。
 */
public class BufferedInputStreamDemo {
    public static void main(String[] args) throws IOException {
        // BufferedInputStream(InputStream in)
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
                "bos.txt"));

        // 讀取資料
        // int by = 0;
        // while ((by = bis.read()) != -1) {
        // System.out.print((char) by);
        // }
        // System.out.println("---------");

        byte[] bys = new byte[1024];
        int len = 0;
        while ((len = bis.read(bys)) != -1) {
            System.out.print(new String(bys, 0, len));
        }

        // 釋放資源
        bis.close();
    }
}

outputStream和inputStream綜合例子

/*
 * 需求:把e:\\哥有老婆.mp4複製到當前專案目錄下的copy.mp4中
 * 
 * 位元組流四種方式複製檔案:
 * 基本位元組流一次讀寫一個位元組:   共耗時:117235毫秒
 * 基本位元組流一次讀寫一個位元組陣列: 共耗時:156毫秒
 * 高效位元組流一次讀寫一個位元組: 共耗時:1141毫秒
 * 高效位元組流一次讀寫一個位元組陣列: 共耗時:47毫秒
 */
public class CopyMp4Demo {
    public static void main(String[] args) throws IOException {
        long start = System.currentTimeMillis();
        // method1("e:\\哥有老婆.mp4", "copy1.mp4");
        // method2("e:\\哥有老婆.mp4", "copy2.mp4");
        // method3("e:\\哥有老婆.mp4", "copy3.mp4");
        method4("e:\\哥有老婆.mp4", "copy4.mp4");
        long end = System.currentTimeMillis();
        System.out.println("共耗時:" + (end - start) + "毫秒");
    }

    // 高效位元組流一次讀寫一個位元組陣列:
    public static void method4(String srcString, String destString)
            throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
                srcString));
        BufferedOutputStream bos = new BufferedOutputStream(
                new FileOutputStream(destString));

        byte[] bys = new byte[1024];
        int len = 0;
        while ((len = bis.read(bys)) != -1) {
            bos.write(bys, 0, len);
        }

        bos.close();
        bis.close();
    }

    // 高效位元組流一次讀寫一個位元組:
    public static void method3(String srcString, String destString)
            throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
                srcString));
        BufferedOutputStream bos = new BufferedOutputStream(
                new FileOutputStream(destString));

        int by = 0;
        while ((by = bis.read()) != -1) {
            bos.write(by);

        }

        bos.close();
        bis.close();
    }

    // 基本位元組流一次讀寫一個位元組陣列
    public static void method2(String srcString, String destString)
            throws IOException {
        FileInputStream fis = new FileInputStream(srcString);
        FileOutputStream fos = new FileOutputStream(destString);

        byte[] bys = new byte[1024];
        int len = 0;
        while ((len = fis.read(bys)) != -1) {
            fos.write(bys, 0, len);
        }

        fos.close();
        fis.close();
    }

    // 基本位元組流一次讀寫一個位元組
    public static void method1(String srcString, String destString)
            throws IOException {
        FileInputStream fis = new FileInputStream(srcString);
        FileOutputStream fos = new FileOutputStream(destString);

        int by = 0;
        while ((by = fis.read()) != -1) {
            fos.write(by);
        }

        fos.close();
        fis.close();
    }
}
## 以上都是通過位元組流讀取資料 ##

使用字元流讀取資料

概述

字元流(掌握)
(1)位元組流操作中文資料不是特別的方便,所以就出現了轉換流。
   轉換流的作用就是把位元組流轉換字元流來使用。
(2)轉換流其實是一個字元流
    字元流 = 位元組流 + 編碼表
(3)編碼表
    A:就是由字元和對應的數值組成的一張表
    B:常見的編碼表
        ASCII
        ISO-8859-1
        GB2312
        GBK
        GB18030
        UTF-8
    C:字串中的編碼問題
        編碼
            String -- byte[]
        解碼
            byte[] -- String
(4)IO流中的編碼問題
    A:OutputStreamWriter
        OutputStreamWriter(OutputStream os):預設編碼,GBK
        OutputStreamWriter(OutputStream os,String charsetName):指定編碼。
    B:InputStreamReader
        InputStreamReader(InputStream is):預設編碼,GBK
        InputStreamReader(InputStream is,String charsetName):指定編碼
    C:編碼問題其實很簡單
        編碼只要一致即可
**(5)字元流
    Reader
        |--InputStreamReader
            |--FileReader
        |--BufferedReader
    Writer
        |--OutputStreamWriter
            |--FileWriter
        |--BufferedWriter**

這裡的讀取方式和上面的FileinputStream,FileOutputStream的讀取方式相似,下面只展示一次讀取一個位元組的讀取方式

public class IOTest2 {
    public static void main(String[] args) {
        try {
            InputStreamReader isr=new InputStreamReader(new FileInputStream("test.txt"),"UTF-8");//這裡需要指定編碼,如果你的檔案是以UTF-8編碼的話,如果想要讀出中文,後面就需要用UTF-8解碼
            OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("test.txt",true),"UTF-8");//這裡也是同理
            osw.write("釣魚島是中國的");
            osw.close();
            int b=0;
            while((b=isr.read())!=-1){
                System.out.print((char)b);

            }
        } catch (Exception e) {
        }

    }
}


還有一個常用的IO流就是FileReader和FileWriter是inputStreamReader和outputStreamWriter的子類,用法類似,具體的可以通過查詢API文件瞭解相關用法