1. 程式人生 > >Java:位元組流、字元流

Java:位元組流、字元流

1、IO概述- IO流概述及分類

1)、IO流:

I:Input(輸入):資料從外部流向程式中。(外部:檔案)

O:Ouput(輸出):資料從程式流向外部。

流:線性的,有方向的

2)、作用:

可以“讀”,“寫”檔案的內容,File類只能獲取檔案/目錄的一些屬性資訊,但不能讀寫檔案內容,只有IO流可以

3)、Java的IO流體系結構:

位元組流:按位元組讀寫檔案,可以操作任何型別檔案(純文字,二進位制…)

字元流:按字元讀寫檔案,僅可以讀寫純文字檔案

輸入流 輸出流
位元組流 位元組輸入流InputStream
字元流 字元輸入流Reader

這裡寫圖片描述

2、位元組流-一切皆位元組

1)、一切皆為位元組:任何檔案(純文字,二進位制…)最終在磁碟上儲存的都是“二進位制”,Java處理這些二進位制的最小單位就是“位元組(8位)”

2)、“位元組流”是Java中IO流中最基本的流,任何其他的流都是基於位元組流的

3、位元組流-位元組輸出流-父類OutputStream的輸出方式

1)、java.io.OutputStream(抽象類):位元組輸出流的父類;

2)、定義輸出的方法:

  • public void close() :關閉此輸出流並釋放與此流相關聯的任何系統資源。
  • public void flush() :重新整理此輸出流並強制任何緩衝的輸出位元組被寫出。
  • public void write(byte[] b):輸出一個位元組陣列
  • public void write(byte[] b, int off, int len) :輸出位元組陣列的一部分(從索引為off處開始,往後len個數組元素)
  • public abstract void write(int b) :輸出一個位元組。

4、位元組流-位元組輸出流-子類FileOutputStream的輸出方法和追加寫入及換行

1)、java.io.FileOutputStream(子類):是檔案輸出流,用於將資料寫出到檔案。

2)、構造方法:

  • public FileOutputStream(File file)
    :建立檔案輸出流以寫入由指定的 File物件表示的檔案。覆蓋寫
  • public FileOutputStream(String name): 使用指定檔名構造一個輸出流。覆蓋寫

  • public FileOutputStream(File file, boolean append): 建立檔案輸出流以寫入由指定的 File物件表示的檔案。 追加寫

  • public FileOutputStream(String name, boolean append): 建立檔案輸出流以指定的名稱寫入檔案。 追加寫

    注意:

    1)、Java中任何輸出流,構造時檔案都可以不存在,會自動建立一個空的檔案。

    2)、Java的IO流不要構造在一個存在的目錄上,會執行異常;如果是不存在的目錄,就會建立一個沒有後綴名的檔案

    3)、操作同一個檔案時,FileOutputStream使用覆蓋寫的構造方法會把原檔案覆蓋

3)、輸出的方法:(沒有特殊方法,都是從父類繼承的)

  • write(byte[] b):輸出一個位元組陣列(write(“字串”.getBytes())),常用於輸出字串

  • write(byte[] b, int off, int len) :從指定的位元組陣列寫入 len位元組,從偏移量 off開始輸出到此輸出流。(從off開始,寫入往後len個位元組陣列元素)

  • write(int b) :輸出一個位元組。

    public static void main(String[] args) throws IOException {
       //1.FileOutputStream(String pathName)
       FileOutputStream out = new FileOutputStream("demo02.txt",true);
    
       //2.FileOutputStream(File file)
    //     FileOutputStream out2 = new FileOutputStream(new File("demo02_2.txt"));
    
       //1.write(int b):輸出一個位元組
       out.write(97);
       out.write(98);
    
       //2.write(byte[] byteArray):輸出多個位元組(一個byte[]陣列)
       String s = "你好";
       out.write(s.getBytes());
       out.write("\r\n".getBytes());//換行
    
       out.write("97".getBytes());
       out.write("\r\n".getBytes());//換行
    
       //3.write(byte[] byteArray,int off,int len):
       byte[] byteArray = {97, 98, 99, 100, 101};
       //只需要輸出:c,d,e
       out.write(byteArray,2,3);
    
       //關閉
       out.close();
    
    }

5、位元組流-位元組輸入流-父類InputStream的讀取方法

1)、java.io.InputStream(抽象類):所有直接輸出流的父類;

2)、讀取的方法:

  • public void close() :關閉此輸入流並釋放與此流相關聯的任何系統資源。
  • public abstract int read():讀取一個位元組。
  • public int read(byte[] b):讀取位元組陣列。(返回值是讀到的位元組陣列長度)

6、位元組流-位元組輸入流-子類FileInputStream的讀取方法

1)、java.io.FileInputStream(子類)是檔案輸入流,從檔案中讀取位元組。

2)、構造方法:

  • FileInputStream(File file): 通過開啟與實際檔案的連線來建立一個 FileInputStream ,該檔案由檔案系統中的 File物件 file命名。

  • FileInputStream(String name): 通過開啟與實際檔案的連線來建立一個 FileInputStream ,該檔案由檔案系統中的路徑名 name命名。

    注意:

    1)、Java中所有的輸入流構造時,檔案必須存在,否則執行異常

2)、讀取的方法是從父類繼承的:

  • public int read():讀取一個位元組

  • public int read(byte[] byteArray):讀取一個位元組陣列

    public static void main(String[] args) throws IOException {
      FileInputStream in = new FileInputStream("demo03.txt");
    
      //1.讀取一個位元組
     /* int b = 0;
      while((b = in.read()) != -1) {
          System.out.println("讀取的位元組:" + b);
          System.out.println("轉換為字元:" + (char) b);
      }*/
    
     //2.讀取一個位元組陣列
      byte[] byteArray = new byte[3];
      int len = 0;
      while((len = in.read(byteArray)) != -1) {
          System.out.println("返回值:" + len);
          System.out.println("陣列內容:" + Arrays.toString(byteArray));
      }
    
      in.close();
    }

7、位元組流-位元組流練習-圖片複製

public static void main(String[] args) throws IOException {
        //1.構造一個到原始檔的:輸入流
        FileInputStream in = new FileInputStream("d:\\douyu.exe");
        //2.構造一個到目標檔案的:輸出流
        FileOutputStream out = new FileOutputStream("e:\\douyu_copy2.exe");//建立一個空檔案

        //3.開始複製--慢
        //1.一次讀、寫一個位元組
        /*int b = 0;
        while ((b = in.read()) != -1) {
            out.write(b);
        }
*/
        //2.一次讀、寫多個位元組--快
        byte[] byteArray = new byte[1024 * 8];
        int len = 0;
        while ((len = in.read(byteArray)) != -1) {
            out.write(byteArray,0,len);
        }
        out.close();
        in.close();

        System.out.println("複製完畢!");
    }

8、字元流-概述

1)、字元流:一次按一個字元讀取,每個國家的字元佔用的位元組數是不同的,(UTF-8,漢字佔用3個位元組)

2)、各個國家使用的編碼表不同,字元佔用的位元組數也就不同,如果都使用“位元組流”讀寫就會很不方便,所以Java提供了一種專門操作純文字檔案的字元流

9、字元流-字元輸出流-父類Writer的輸出方法

1)、java.io.Writer(抽象類):所有字元輸出流的父類

2)、常用方法:

  • public abstract void close() :關閉此輸出流並釋放與此流相關聯的任何系統資源。(自帶重新整理和關閉流)
  • public abstract void flush() :重新整理此輸出流並強制任何緩衝的輸出字元被寫出。
  • public void write(int c) :輸出一個字元
  • public void write(char[] cbuf):輸出一個字元陣列
  • public abstract void write(char[] b, int off, int len) :輸出字元陣列的一部分
  • public void write(String str) :輸出一個字串

注意:在使用字元流輸出字元和字串後,字元流會建立一個快取區,必須對快取區進行重新整理(flush()或close()),才會寫入檔案中

10、字元流-字元輸出流-子類FileWriter類的使用

1)、java.io.FileWriter(子類)

2)、構造方法:

  • FileWriter(File file): 建立一個新的 FileWriter,給定要讀取的File物件。

  • FileWriter(String fileName): 建立一個新的 FileWriter,給定要讀取的檔案的名稱。

  • FileWriter(String fileName,boolean append):構造一個FileWriter物件,給出一個帶布林值的檔名,表示是否附加寫入資料

  • FileWriter(File file,boolean append): 建立一個新的 FileWriter,給定要讀取的File物件,布林值表示時候附加寫入資料

    public static void main(String[] args) throws IOException {
      FileWriter out = new FileWriter("demo06.txt");//覆蓋寫
      // FileWriter out2 = new FileWriter("demo06.txt", true);//追加寫
    
      //1.writer(int c):
      out.write('你');
      out.write('a');
    
      //2.write(char[] chArray)
      out.write("你好".toCharArray());
      char[] chArray = {'a','b','你','好','啊','恩'};
      out.write(chArray);
      //3.write(char[] chArray,int off,int len):
      //只輸出:好,啊,恩
      out.write(chArray,3,3);
    
      //4.write(String s):
      out.write("呵呵");
      out.write("\r\n");
    
      //5.write(String s,int off,int len)
      String s = "我愛Java";
      //要求輸出:s中的Java
      out.write(s,2,4);
    
      //out.flush();//重新整理快取區
    
       out.close();//flush() + close()(建議)
    }

11、字元流-字元輸入流-父類Reader的讀取的方法

1)、java.io.Reader(抽象類)

2)、常用方法:

  • public void close() :關閉此流並釋放與此流相關聯的任何系統資源。
  • public int read(): 讀取一個字元,返回值:字元的編碼
  • public int read(char[] cbuf):讀取一個字元陣列,返回值:字元數量

12、字元流-字元輸入流-子類-FileReader類的使用

1)、java.io.FileReader(子類)

2)、構造方法:

  • FileReader(File file): 建立一個新的 FileReader ,給定要讀取的File物件。

  • FileReader(String fileName): 建立一個新的 FileReader ,給定要讀取的檔案的名稱。

    public static void main(String[] args) throws IOException {
      File file = new File("demo07.txt");
      if (!file.exists()) {
          file.createNewFile();
      }
    
      FileReader in = new FileReader(file);
    
      //一次讀取一個字元
      /*int c = 0;
      while ((c = in.read()) != -1) {
          System.out.println("讀取的字元:" + (char)c);
      }*/
    
      //一次讀取一個字元陣列
      char[] chArray = new char[2];
      int len = 0;
      while ((len = in.read(chArray)) != -1) {
          System.out.println(chArray);
      }
      in.close();
    }

13、IO異常處理-JDK7前的處理

public static void main(String[] args) {
    FileReader in = null;
    try {
         in = new FileReader("demo07.txt");
        //一次讀取一個字元陣列
        char[] chArray = new char[2];
        int len = 0;
        while ((len = in.read(chArray)) != -1) {
            System.out.println(chArray);
        }

    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }finally {
        if (in != null) {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }
}

14、IO異常處理-JDK7和JDK8的處理方式(開發常用)

public class Demo {
    public static void main(String[] args) {
        try (
                //in物件不需要我們關閉,會自動關閉
                FileReader in = new FileReader("demo07.txt");
        ) {
            //一次讀取一個字元陣列
            char[] chArray = new char[2];
            int len = 0;
            while ((len = in.read(chArray)) != -1) {
                System.out.println(chArray);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

15、IO異常處理-JDK9改進的處理方式

public class Demo {
    public static void main(String[] args) throws IOException {
        //假設,這兩個物件不是我們建立的,從其它地方獲取的,但需要我們用完後關閉。
        FileWriter out = new FileWriter("demo10.txt");
        FileReader in = new FileReader("demo10_2.txt");

        //寫在try(...)中的物件,在用完後會自動關閉。
        try (in; out) {
            char[] chArray = new char[1024];
            int len = 0;
            while ((len = in.read(chArray)) != -1) {
                out.write(chArray, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

16、屬性集-Properties類概述

1)、java.util.Properties(類):此類是一個Map集合

2)、此類中有倆個方法可以用於方便的讀、寫配置檔案;

3)、配置檔案:指軟體執行過程中記錄使用者的一些設定資訊的檔案,這種配置檔案在國際上有一個通用的格式:

名1 = 值;

名2 = 值;

這種格式與Map的鍵值對格式正好匹配,所以製作了一個Map集合,Properties方便讀取配置檔案

4)、Properties集合 –> 配置檔案;配置檔案 –>Properties集合

17、屬性集-Properties類與流相關的方法介紹

Properties集合 –> 配置檔案:store()方法

配置檔案 –>Properties集合:load()方法

public class Demo {
    public static void main(String[] args) throws IOException {
//        write();
       read();

    }

    private static void read() throws IOException {
        Properties pro = new Properties();

        FileReader in = new FileReader("demo11.txt");
        pro.load(in);//一次性將配置檔案中所有的鍵值對全部讀取到集合中
        in.close();

        /*Set<Object> keys = pro.keySet();
        for (Object o : keys) {
            System.out.println(o + " = " + pro.get(o));
        }*/

        Set<String> keys = pro.stringPropertyNames();
        for (String k : keys) {
            System.out.println(k + " = " + pro.getProperty(k));
        }

    }

    private static void write() throws IOException {
        Properties pro = new Properties();

        pro.setProperty("金幣", "500000");//相當於:put(Object key,Object value)
        pro.setProperty("鑽石", "200000");
        pro.setProperty("疲勞", "120");
        pro.setProperty("血量", "100");

        //存到配置檔案
        FileWriter out = new FileWriter("demo11.txt");
        pro.store(out,"Hello");//將集合中所有的鍵值對一次性的寫入到檔案.
        out.close();
    }
}

複習

  • [ ] 能夠說出IO流的分類和功能

    1)、位元組流:按位元組讀寫檔案,可以讀寫任何檔案

    2)、字元流:按字元讀寫檔案,只能操作“純文字”檔案

  • [ ] 能夠使用位元組輸出流寫出資料到檔案

    FileOutputStream out = new FileOutputStream("demo01.txt");
    out.write(97);
    out.close();
  • [ ] 能夠使用位元組輸入流讀取資料到程式

    FileInputStream in = new FileInputStream("demo01.txt");
    byte[] bytes = new byte[1024];
    int len = 0;
    while((len = in.read(bytes))!=-1){
      String s = new String(bytes,0,len);
    System.out.println("讀取的內容:" + s);
    }
  • [ ] 能夠理解讀取資料read(byte[])方法的原理

  • [ ] 能夠使用位元組流完成檔案的複製

  • [ ] 能夠使用FileWirter寫資料到檔案

  • [ ] 能夠說出FileWriter中關閉和重新整理方法的區別

  • [ ] 能夠使用FileWriter寫資料的5個方法

  • [ ] 能夠使用FileWriter寫資料實現換行和追加寫

  • [ ] 能夠使用FileReader讀資料

  • [ ] 能夠使用FileReader讀資料一次一個字元陣列

  • [ ] 能夠使用Properties的load方法載入檔案中配置資訊