IO流(02)–屬性集、緩衝流、轉換流

  • 2020 年 12 月 16 日
  • 筆記

屬性集【Properties】

java.util.Properties類繼承於Hashtable,用來表示一個持久的屬性集。它使用鍵值結構存儲數據,每個鍵及其對應的值都是一個字元串。

構造方法
  • ​ public Properties():創建一個空的屬性集列表。
共性的api方法
  • public Object setProperty(String key,String value):保存一對屬性。
  • public String getProperty(String key):使用此屬性列表中的指定的鍵搜索對應的值。
  • public Set stringPropertyNames():獲取所有鍵的名稱並封裝到Set集合中。
public static void main(String[] args) {
        // 創建屬性集對象
        Properties properties = new Properties();
        // 添加鍵值對元素
        properties.setProperty("name", "abc.txt");
        properties.setProperty("size", "12000");
        properties.setProperty("destination","D:\\abc.txt");
        properties.put("data","小孫");
        System.out.println(properties);// {destination=D:\abc.txt, name=abc.txt, size=12000}

        // 通過鍵來獲取值
        String data = properties.getProperty("data");
        System.out.println(data); // 小孫
        String size = properties.getProperty("size");
        System.out.println(size);// 12000

        // 遍歷該屬性集
        // public Set<String> stringPropertyNames():獲取所有鍵的名稱並封裝到Set集合中。
        Set<String> keys = properties.stringPropertyNames();
        // 遍歷keys
        for (String key : keys) {
            // 通過key獲取value
            String value = properties.getProperty(key);
            System.out.println(key + "=" + value);
        }

    }
與流相關的方法
  • public void load(InputStream input):從位元組輸入流中讀取鍵值對

參數中使用了位元組輸入流,通過流對象,可以關聯到某個文件上,這樣既可以載入文件中的數據。文件中的數據的格式:key=value

例如:
   data=小孫
   size=12000  
   name=abc.txt

程式碼演示:

public static void show01() throws IOException {
        // 0.構建一個流對象
        FileReader fr = new FileReader("day29_IO\\abc.txt");
        // 1.創建Properties集合
        final Properties properties = new Properties();
        //  2.使用Properties集合中的方法load讀取保存在輸入流中的數據
        properties.load(fr);
        //  3.遍歷Properties集合
        final Set<String> set = properties.stringPropertyNames();
        for (String key : set) {
            // 通過key獲取value值
            final String value = properties.getProperty(key);
            System.out.println(key + "=" + value);
        }
        /*
            name=abc.txt
            size=12000
            data=小孫
            目的地=D:\abc.txt
         */
    }
  • ​ public void store(OutputStream out,String comments):把集合當中數據寫入位元組輸出流中

可以使用Properties集合當中的方法store,把集合當中的臨時數據,持久化寫入到硬碟文件中保存。

程式碼示例:

public static void show02() throws IOException {
        // 1. 創建Properties集合對象,添加數據
        final Properties properties = new Properties();
        properties.setProperty("四大名著1","紅樓夢");
        properties.setProperty("四大名著2","西遊記");
        properties.setProperty("四大名著3", "水滸傳");
        properties.setProperty("四大名著4", "三國演義");
        // 2. 創建位元組輸出流/字元輸出流對象,構造方法中綁定需要寫入數據的目的地
        final FileWriter fw = new FileWriter("day29_IO\\abcd.txt", true);
        // 3. 使用Properties集合中的方法store,把集合當中的臨時數據,持久化寫入到硬碟當中存儲
        properties.store(fw, "si da ming zhu");
        // 4.釋放資源。
        fw.close();
}

緩衝流【Buffered】

緩衝流我們理解為對原來的使用數組方式進行數據傳輸的一種增強

按照類型分為:

  • 字元緩衝流:BufferedReader,BufferedWriter
  • 位元組緩衝流:BufferedInputStream,BufferedOutputStream

緩衝流的基本原理,是在創建流對象的時候,會創建一個內置的默認大小的緩衝區數組,通過緩衝區讀寫數據,減少系統IO操作的次數,減少開銷,提高程式的讀寫的效率。

位元組緩衝流
構造方法
  • public BufferedInputStream(InputStream input):創建一個新的緩衝輸入流
  • public BufferedOutputStream(OutputStream output):創建一個新的緩衝輸出流

程式碼示例:

public class Demo02 {
    public static void main(String[] args) throws IOException {
        // 1.創建一個FileOutputStream流對象,構造方法中標的需要綁定寫入數據的數據源
        FileInputStream fis = new FileInputStream("day29_IO\\one.txt");
        // 2.創建BufferedInputStream對象,構造方法中傳遞FileInputStream流對象
        BufferedInputStream bis = new BufferedInputStream(fis);
        //3.使用BufferedInputStream對象指定方法read,把數據讀取到記憶體中
        /*int len = 0;
        while ((len=bis.read())!=-1){
            System.out.println((char)len);
        }*/
        byte[]bytes = new byte[1024];
        int len = 0;
        while ((len=bis.read(bytes))!=-1){
            System.out.println(new String(bytes,0,len));
        }
        //4.釋放資源
        bis.close();
    }
}

字元緩衝流

構造方法

  • public BufferedWriter(Writer out):創建一個 新的字元緩衝輸出流

  • public BufferedReader(Reader in):創建一個新的字元緩衝輸入流。

特有方法:

  • BufferedReader: public String readLine():讀取整行的文本資訊

  • BufferedWriter: public void newLine():寫入一行的行分隔符,由系統屬性定義換行符號。

字元緩衝輸入流程式碼演示:

public static void main(String[] args) throws IOException {
        //1.創建一個字元緩衝輸入流對象,構造方法中傳入一個字元輸入流
        BufferedReader br = new BufferedReader(new FileReader("day29_IO\\abc.txt"));
        //2.使用字元緩衝流對象中的read/readLine,
       /* String str = br.readLine();
        System.out.println(str);*/
        //循環結束條件readLine()返回值是null的時候
        String str = null;
        while ((str=br.readLine())!=null){
            System.out.println(str);
        }
        //3.釋放資源。
        br.close();
    }

字元緩衝輸出流程式碼演示:

public static void main(String[] args) throws IOException {
        // 1.創建一個字元緩衝輸出流對象,構造方法中傳遞一個字元輸出流
        BufferedWriter bw = new BufferedWriter(new FileWriter("day29_IO\\two.txt"));
        //2.調用字元流對象中的writer,把數據寫入到記憶體存儲區中
        bw.write("我今天學習了PS,雖然沒學會");
        bw.newLine();
        bw.write("3D軟體mmd");
        bw.newLine();
        bw.write("c4d");
        // 3.調用字元緩衝輸出流對象的flush方法,把你想緩衝區的數據刷新到文件中
        bw.flush();
        //4.釋放資源
        bw.close();
    }

練習:

 public static void show02() throws IOException {
        long start = System.currentTimeMillis();
        //1.構建位元組緩衝輸入流對象
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("C:\\Users\\Administrator\\Desktop\\0.jpg"));
        //2.構建個位元組緩衝輸出流
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("E:\\code\\java31\\day29_IO\\0.jpg"));
        //3.用位元組緩衝輸入流對象中的方法read(byte[] b)讀取文件
        byte[]bytes = new byte[1024];

        int len = 0;//記錄讀取到有效位元組個數
        while ((len = bis.read(bytes))!=-1){
            //節內容再次寫入到目的地文件中,調用write
            bos.write(bytes,0,len);
        }
        bos.close();
        bis.close();

        long end= System.currentTimeMillis();
        System.out.println("文件複製耗費的時間為:"+(end-start));
    }

轉換流【位元組流<–>字元流】

  • 字元編碼:
      按照某種規則將字元存儲到電腦中,稱為編碼;反之,將存儲在電腦中的二進位數按照某種規則解析顯示出來,稱為解碼。在進行編碼或者解碼的過程中,我們採用的是同一種規則,才能數據正常,否則,就會導致亂碼現象。就是一套自然語言中的字元與二進位數直接的對應規則。

  • 字符集:
      是一個系統可支援的所有字元的集合,包括各國文字,標點符號,圖形符號,數字等,也叫編碼表。

電腦中要準確的存儲和識別各種文字的字元符號,需要進行字元編碼,一套字符集至少有一套字元編碼。

常見的字元編碼集有ASCII字符集,GBK字符集、Unicode字符集。

ASCII字符集:

  • ASCII是基於拉丁字母的一套編碼系統,用於顯示現代英語。

  • 基本的ASCII字符集,使用7位(bit)表示一個字元,共128個字元。ASCII的擴展字符集使用8位(bit)表示一個字元,共25
    6個字元。

ISO—8859-1字符集

  • 拉丁碼錶,別名–Lanlin-1,用於顯示歐洲使用的語言,包括荷蘭,丹麥,德語,義大利語,西班牙語等。

  • ISO-8859-1使用單位元組編碼,兼容ASCII編碼。

GB系列符集

  • CB2312:稱為簡體中文碼錶裡面大概含有7000多個簡體漢字,此外數字元號。羅馬希臘的字母,日本的假名都編進去了,連在ASCII里的原來就有的數字、標點、字母都統統重新用兩個位元組編寫進去了。

  • GBK:最常用的中文碼錶。是在原來的GB2312碼錶基礎上進行了擴展。也是使用雙位元組編碼。共收錄了21000多個漢字,完全兼容GB2312標準,同時支援繁體漢字以及日韓漢字等。

  • GB18030:最新的中文碼錶,共收錄了7萬多個漢字,採用多位元組編碼,每個字可以由1個位元組、2個位元組或者是4個位元組組成,支援中國少數民族的文字。同時也支援繁體字以及日韓漢字等。

Unicode字符集:

  • Unicode編碼系統為表達任意語言的任意字元而設計的,是業界的一種標準,也稱為統一編碼,標準萬國碼錶

  • 它最多使用4個位元組的數字來表示某個字母、符號、漢字文字,有三種常見的編碼方案:UTF-8,UTF-6,UTF-32.

  • UTF-8編碼表,用來表示Unicode標準中的任意字元,編碼規則:

  1.128個US-ASCII字元,使用的是一個位元組編碼
  2.拉丁字的字母,需要兩個位元組編碼
  3.大部分常見的漢字,使用的是三個位元組編碼
  4.其他極少數的輔助字元,採用的四個位元組編碼。

編碼會引發的問題

由於編碼規則不一致,導致引發亂碼現象。

那麼如何讀取GBK編碼的文件呢?

InputStreamReader類

轉換流 java.io.InputStreamReader 是Reader的子類,它是從位元組流到字元流的橋樑。它讀取位元組,並使用指定的字符集將其解碼為字元。它的字符集可以由名稱指定,或者可以使用平台默認的字符集。

構造方法
  • public InputStreamReader(InputStream in):創建一個使用默認的字符集的字元流。

  • public InputStreamReader(InputStream in,String charseName):創建一個指定字符集的字元流

程式碼演示:

 public static void show01() throws IOException {
        //1.創建InputStreamReader對象,構造方法中傳遞位元組輸入流和指定的編碼表名稱
        InputStreamReader isr = new InputStreamReader(new FileInputStream("day29_IO\\新建文本文檔.txt"), "GBK");
        //2.使用InputStreamReader對象中的方法read讀取文件中的資訊
        int len = 0;
        while ((len=isr.read())!=-1) {
            System.out.println((char)len);
        }
        //3.釋放資源。
        isr.close();
    }

OutStreamWriter類

轉換流java.io.OtputSreamWiter是Writer的子類,它是字元流到位元組流的橋樑。使用指定的字符集將字元編碼為位元組。它的字符集可以手動指定,也可以使用平台默認的字符集。

構造方法:

  • public OutputStreamWriter(OutputStream out): 創建一個使用普通默認的字符集的字元流。

  • public OutputStreamWriter(OutputStream out,String charseName):創建一個指定的字符集字元流。