3/23day17_緩沖流_轉(zhuǎn)換流_序列化流_打印流_裝飾設(shè)計(jì)模式_common-io 工具包

復(fù)習(xí)

1.字符流
    FileWriter FileReader
2.ResourceBundle
3.Properties
    a.都可以讀取Properties配置文件
    區(qū)別:
        a.ResourceBundle是靜態(tài)方法getBundle,Properties成員方法load
        b.ResourceBundle一般讀取src根目錄下,Properties一般讀取項(xiàng)目根目錄下
        c.ResourceBundle讀取時(shí)只需要寫文件名(不帶后綴), Properties讀取時(shí)文件名要寫全名
            
4.異常處理    
    JDK1.7之前
        try{
            
        }catch(Exception e){
            
        }finally{
            xxx.close();
        }
    JDK1.7以及之后
        try(FileReader fr = new FileReader("1.txt")){
            
        }catch(Exception e){
            
        }
    

今日內(nèi)容

  • 緩沖流(高效流, 比普通流性能更高)
  • 轉(zhuǎn)換流(編碼相關(guān)的流, 指定編碼)'
  • 序列化流(操作對(duì)象)
  • 打印流(System.out.println())
  • 設(shè)計(jì)模式(裝飾設(shè)計(jì)模式, 4個(gè)步驟)
  • common-io 工具包(簡(jiǎn)化io代碼)

緩沖流

緩沖流的介紹

  • 介紹

    緩沖流,也叫高效流,是對(duì)4個(gè)基本的 FileXxx 流的增強(qiáng)(性能增強(qiáng), 方法基本一樣),所以也是4個(gè)流

  • 緩沖流的基本原理,是在創(chuàng)建流對(duì)象時(shí),會(huì)創(chuàng)建一個(gè)內(nèi)置的默認(rèn)大小的緩沖區(qū)數(shù)組,通過(guò)緩沖區(qū)讀寫,減少系統(tǒng)IO次數(shù),從而提高讀寫的效率。

緩沖流的分類

  • 按照數(shù)據(jù)類型分類:

    緩沖字節(jié)輸入流: BufferedInputStream ---> 對(duì)普通的字節(jié)輸入流``InputStream`增強(qiáng)

    緩沖字節(jié)輸出流: BufferedOutputStream ---> 對(duì)普通的字節(jié)輸出流OutputStream增強(qiáng)

    緩沖字符輸入流: BufferedReader ---> 對(duì)普通的字符輸入流Reader增強(qiáng)

    緩沖字符輸出流: BufferedWriter ---> 對(duì)普通的字符輸出流Writer增強(qiáng)

字節(jié)緩沖流的介紹和使用

  • 字節(jié)緩沖流的構(gòu)造

    public BufferedInputStream(InputStream in):創(chuàng)建一個(gè) 新的緩沖輸入流。
    public BufferedOutputStream(OutputStream out): 創(chuàng)建一個(gè)新的緩沖輸出流。

  • 字節(jié)緩沖流的使用代碼

    (使用一次讀取一個(gè)字節(jié)數(shù)組的方式,配合字節(jié)緩沖流使用速度更快)

        public static void copy01() throws Exception{
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream("1.txt"));
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("2.txt"));
            long start = System.currentTimeMillis();
            int b = 0;
            while ((b = bis.read()) != -1) {
                bos.write(b);
            }
            long end = System.currentTimeMillis();
            bis.close();
            bos.close();
            System.out.println(end-start);
        }
    

字符緩沖流的介紹和使用

  • 字符緩沖流的構(gòu)造

    public BufferedReader(Reader in):創(chuàng)建一個(gè) 新的緩沖輸入流。
    public BufferedWriter(Writer out): 創(chuàng)建一個(gè)新的緩沖輸出流。

  • 字符緩沖流的特有方法

    BufferedReadpublic String readLine() : 讀一行文字(只要沒到換行)。(讀不到會(huì)返回null)
    BufferedWriterpublic void newLine() : 寫一行行分隔符(換行符),由系統(tǒng)屬性定義符號(hào)(具有跨平臺(tái)性)。

    • BufferedRead的一次讀取一行使用

      public static void bwread() throws IOException{
          BufferedReader br = new BufferedReader(new FileReader("2.txt"));
          System.out.println(br.readLine());
          //===========一次讀取一行的標(biāo)準(zhǔn)寫法==========
          String line="";
          while ((line = br.readLine()) != null) {
              System.out.println(line);
          }
          br.close();
      }
      

      緩沖流練習(xí)

public static void main(String[] args) throws IOException {
    ArrayList<String> list = new ArrayList<>();
    BufferedReader br = new BufferedReader(new FileReader("1.txt"));
    String line ="";
    while ((line = br.readLine()) != null) {
        list.add(line);
    }
    br.close();
    /* Collections.sort(list, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o1.charAt(0)-o1.charAt(0);
            }
        });*/
    Collections.sort(list,((o1, o2) -> o1.charAt(0)-o2.charAt(0)));
    /*for (String s : list) {
            System.out.println(s);
        }*/
    BufferedWriter bw = new BufferedWriter(new FileWriter("2"));
    for (String s : list) {
        bw.write(s);
        bw.newLine();
    }
    bw.close();
}

轉(zhuǎn)換流

編碼和解碼

  • 編碼: 把字符按照某種規(guī)則,將字符轉(zhuǎn)到字節(jié)(二進(jìn)制)存儲(chǔ)到計(jì)算機(jī)中,稱為編碼 。

  • 解碼: 將存儲(chǔ)在計(jì)算機(jī)中的二進(jìn)制數(shù)按照某種規(guī)則解析顯示出來(lái),稱為解碼 。

字符集

字符集 Charset :也叫編碼表。是一個(gè)系統(tǒng)支持的所有字符的集合,包括各國(guó)家文字、標(biāo)點(diǎn)符號(hào)、圖形符號(hào)、數(shù)字等。

字符編碼

字符編碼 Character Encoding : 就是一套自然語(yǔ)言的字符與二進(jìn)制數(shù)之間的對(duì)應(yīng)規(guī)則。

常見的字符集和字符編碼

ASCII 字符集 --> ASCII 編碼 , 規(guī)定了ASCII字符集中所有的字符都占1個(gè)字節(jié)(0-127)用于顯示現(xiàn)代英語(yǔ),主要包括控制字符(回車鍵、退格、換行鍵等)和可顯
示字符(英文大小寫字符、阿拉伯?dāng)?shù)字和西文符號(hào))。

GBK字符集 ---> GBK編碼, 規(guī)定所有的中文字符都占2個(gè)字節(jié)(這2個(gè)字節(jié)都是負(fù)數(shù)).是為了顯示中文而設(shè)計(jì)的一套字符集。

Unicode字符集 ---> UTF-8編碼, 規(guī)定所有中文字符都占3個(gè)字節(jié),Unicode編碼系統(tǒng)為表達(dá)任意語(yǔ)言的任意字符而設(shè)計(jì),是業(yè)界的一種標(biāo)準(zhǔn),也稱為統(tǒng)一碼、標(biāo)準(zhǔn)萬(wàn)國(guó)碼。

ISO-8859-1字符集 ---> 用于顯示歐洲使用的語(yǔ)言

編碼引出的問(wèn)題

IDEA默認(rèn)使用UTF-8編碼, windows默認(rèn)使用GBK編碼

public class ReaderDemo {
    public static void main(String[] args) throws IOException {
        FileReader fileReader = new FileReader("E:\\File_GBK.txt");
        int read;
        while ((read = fileReader.read()) != -1) {
            System.out.print((char)read);
        }
        fileReader.close();
    }
}
輸出結(jié)果:
???

使用轉(zhuǎn)換流InputStreamReader類解決讀取中文的問(wèn)題

轉(zhuǎn)換流 java.io.InputStreamReader ,是Reader的子類,是從字節(jié)流到字符流的橋梁。它讀取字節(jié),并使用指定的字符集將其解碼為字符。它的字符集可以由名稱指定,也可以接受平臺(tái)的默認(rèn)字符集。

  • 構(gòu)造方法

    InputStreamReader(InputStream in) : 創(chuàng)建一個(gè)使用默認(rèn)字符集的字符流。(使用IDEA默認(rèn)編碼)
    InputStreamReader(InputStream in, String charsetName): 創(chuàng)建一個(gè)指定字符集的字符流。(第二個(gè)參數(shù)為指定使用何種編碼讀取文件)

使用轉(zhuǎn)換流OutputStreamReader類寫不同編碼的中文

轉(zhuǎn)換流 java.io.OutputStreamWriter ,是Writer的子類,是從字符流到字節(jié)流的橋梁。使用指定的字符集將字符編碼為字節(jié)。它的字符集可以由名稱指定,也可以接受平臺(tái)的默認(rèn)字符集。

  • 構(gòu)造方法

    OutputStreamWriter(OutputStream in): 創(chuàng)建一個(gè)使用默認(rèn)字符集的字符流。
    OutputStreamWriter(OutputStream in, String charsetName) : 創(chuàng)建一個(gè)指定字符集的字符流。

  • 按指定編碼輸出

    public static void main(String[] args) throws Exception {
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("1.txt"), "UTF-8");
        osw.write("你好");
        osw.close();
    }
    

轉(zhuǎn)換流的理解

轉(zhuǎn)換流代碼案例

public static void main(String[] args) throws Exception{
    InputStreamReader isr = new InputStreamReader(new FileInputStream("GBK.txt"), "GBK");
    OutputStreamWriter ops = new OutputStreamWriter(new FileOutputStream("UTF-8.TXT"), "UTF-8");
    int ch=0 ;
    while ((ch = isr.read()) != -1) {
        ops.write((char)ch);
    }
    isr.close();
    ops.close();
}

序列化

序列化流概述

  • 序列化流: 寫出對(duì)象的流

    ObjectOutputStream(java.io.ObjectOutputStream 類,將Java對(duì)象的原始數(shù)據(jù)類型寫出到文件,實(shí)現(xiàn)對(duì)象的持久存儲(chǔ)。)

  • 反序列化流: 讀取對(duì)象的流

    ObjectInputStream(ObjectInputStream反序列化流,將之前使用ObjectOutputStream序列化的原始數(shù)據(jù)恢復(fù)為對(duì)象。)

ObjectOutputStream類的介紹和使用

  • 構(gòu)造方法

    public ObjectOutputStream(OutputStream out): 創(chuàng)建一個(gè)指定OutputStream的ObjectOutputStream。

  • 序列化操作的前提

    想要序列化, 必須將需要序列化的對(duì)象類實(shí)現(xiàn)Serializable(可序列化)接口

    Serializable接口沒有需要重寫的方法, 這種接口被稱為標(biāo)記接口

  • 序列化操作代碼演示

        public static void main(String[] args) throws Exception{
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("dog.txt"));
            oos.writeObject(new Dog(20,"小狗狗"));
            oos.close();
        }
    

    寫出的dog.txt文件中是字節(jié)文件.

ObjectInputStream類的介紹和使用

  • 構(gòu)造方法

    public ObjectInputStream(InputStream in) : 創(chuàng)建一個(gè)指定InputStream的ObjectInputStream。

  • 反序列化操作代碼演示

    public static void main(String[] args) throws Exception{
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("dog.txt"));
        Object o = ois.readObject();
        System.out.println(o);
        ois.close();
    }
    

反序列化可能會(huì)出現(xiàn)的異常

  • 對(duì)于JVM可以反序列化對(duì)象,它必須是能夠找到class文件的類。如果找不到該類的class文件,則拋出一個(gè)ClassNotFoundException 異常。

    原因: 找不到序列化時(shí)的對(duì)象類

  • 當(dāng)JVM反序列化對(duì)象時(shí),能找到class文件,但是class文件在序列化對(duì)象之后發(fā)生了修改,那么反序列化操作也會(huì)失敗,拋出一個(gè) InvalidClassException異常。

    原因: 修改了序列化的對(duì)象類的內(nèi)容,根據(jù)版本號(hào)識(shí)別

  • Serializable 接口給需要序列化的類,提供了一個(gè)序列版本號(hào)。 serialVersionUID 該版本號(hào)的目的在于驗(yàn)證序列化的對(duì)象和對(duì)應(yīng)類是否版本匹配。(允許程序員自己管理版本號(hào)代碼如下)

    public class Employee implements java.io.Serializable {
         // 加入序列版本號(hào)
         private static final long serialVersionUID = 1L;
         public String name;
         public String address;
         // 添加新的屬性 ,重新編譯, 可以反序列化,該屬性賦為默認(rèn)值.
         public int eid; 
     
         public void addressCheck() {
             System.out.println("Address  check : " + name + " -- " + address);
         }
    }
    

序列化多個(gè)對(duì)象

  • 注意: 序列化流一個(gè)文件只適合序列化一個(gè)對(duì)象(如果一個(gè)文件序列化多個(gè)對(duì)象, 會(huì)缺少標(biāo)記)

  • 操作步驟:

    1. 把序列化的多個(gè)對(duì)象,保存到一個(gè)集合對(duì)象(集合已經(jīng)實(shí)現(xiàn)了Serializable接口)
    2. 把這個(gè)集合作為對(duì)象,序列化到文件中(其實(shí)就是將集合容器作為對(duì)象序列化到文件中)
  • 序列化多個(gè)對(duì)象代碼演示:

    public class TestDemo {
        public static void main(String[] args) throws Exception {
            write();
            read();
        }
        public static void write() throws IOException {
            ArrayList<Dog> dogs = new ArrayList<>();
            dogs.add(new Dog(23, "dahua"));
            dogs.add(new Dog(11, "erhua"));
            dogs.add(new Dog(55, "sanhua"));
    
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("dogs.txt"));
            oos.writeObject(dogs);
            oos.close();
        }
        public static void read() throws Exception {
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("dogs.txt"));
            Object o  = ois.readObject();
            //反序列化文件, 返回值是Object對(duì)象, 需要強(qiáng)轉(zhuǎn)成集合(泛型用父類多態(tài)接收)
            for (Object dog : (ArrayList<Object>)o) {
                System.out.println(dog);
            }
            ois.close();
        }
    }
    
    

打印流(PrintStream)

打印流的介紹

System.out.println()在控制臺(tái)打印輸出,是調(diào)用print 方法和 println 方法完成的,這兩個(gè)方法都來(lái)自于java.io.PrintStream 類(成為打印流),該類能夠方便地打印各種數(shù)據(jù)類型的值(打印流中重寫了各種數(shù)據(jù)類型的printprintlin方法),是一種便捷的輸出方式。

打印流的用法

  • 構(gòu)造方法

    public PrintStream(String fileName): 使用指定的文件名創(chuàng)建一個(gè)新的打印流。

    public PrintStream(File file): 直接指定file對(duì)象

    public PrintStream(OutputStream out): 輸出流綁定的哪個(gè)對(duì)象, 就打印到哪個(gè)對(duì)象中

  • 成員方法

    public void print(各種數(shù)據(jù)類型);

    public void println(各種數(shù)據(jù)類型);

  • 打印流代碼演示

    public static void main(String[] args) throws Exception{
        PrintStream ps1 = new PrintStream("p.txt");
        PrintStream ps2 = new PrintStream(new File("p1.txt"));
        PrintStream ps3 = new PrintStream(new FileOutputStream("p2.txt"));
        ps1.print("隨便寫各種類型數(shù)據(jù)");
    }
    
  • 修改系統(tǒng)打印流的流向

    public static void main(String[] args)  throws Exception{
        PrintStream ps = new PrintStream("p.txt");
        ps.print("更改打印");
        System.out.println("JAVA");
        //相當(dāng)于修改了System靜態(tài)變量out的值
        System.setOut(ps);
        System.out.println();
        System.out.println("java更改");
    }
    

裝飾設(shè)計(jì)模式

設(shè)計(jì)模式是指, 前輩們?yōu)榱私鉀Q一系列問(wèn)題設(shè)計(jì)的方案

在我們今天所學(xué)的緩沖流中涉及到j(luò)ava的一種設(shè)計(jì)模式,叫做裝飾模式.

裝飾設(shè)計(jì)模式概述(作用)

指在不改變?cè)? 不適用繼承的基礎(chǔ)上, 動(dòng)態(tài)地?cái)U(kuò)展一個(gè)對(duì)象的功能.

裝飾設(shè)計(jì)模式的4個(gè)基本步驟

  • 裝飾類(需要裝飾的新類)和被裝飾類(原類)必須實(shí)現(xiàn)相同的接口(可以將原類中的成員方法抽出來(lái), 放在接口中)
  • 在裝飾類中必須傳入被裝飾類的引用(就是在新類中定義裝飾類的成員變量對(duì)象)
  • 在裝飾類中對(duì)需要擴(kuò)展的方法進(jìn)行擴(kuò)展
  • 在裝飾類中對(duì)不需要擴(kuò)展的方法調(diào)用被裝飾類中的同名方法

裝飾設(shè)計(jì)模式代碼演示

  1. 先提供方法接口

    public interface Star {
        public void sing();
        public void dance();
    }
    
  2. 讓原類去實(shí)現(xiàn)接口

    public class LiuDeHua implements Star {
        @Override
        public void sing() {
            System.out.println("劉德華在唱忘情水...");
        }
        @Override
        public void dance() {
            System.out.println("劉德華在跳街舞...");
        }
    }
    
  3. 寫裝飾類,在裝飾類中擴(kuò)展

    /*
        裝飾模式遵循原則:
            裝飾類和被裝飾類必須實(shí)現(xiàn)相同的接口
            在裝飾類中必須傳入被裝飾類的引用
            在裝飾類中對(duì)需要擴(kuò)展的方法進(jìn)行擴(kuò)展
            在裝飾類中對(duì)不需要擴(kuò)展的方法調(diào)用被裝飾類中的同名方法
    */
    public class LiuDeHuaWarpper implements Star {
        // 存放被裝飾類的引用
        private LiuDeHua liuDeHua;
        // 通過(guò)構(gòu)造器傳入被裝飾類對(duì)象
        public LiuDeHuaWarpper(LiuDeHua liuDeHua){
            this.liuDeHua = liuDeHua;
        }
        @Override
        public void sing() {
            // 對(duì)需要擴(kuò)展的方法進(jìn)行擴(kuò)展增強(qiáng)
            System.out.println("劉德華在鳥巢的舞臺(tái)上演唱忘情水.");
        }
        @Override
        public void dance() {
            // 不需要增強(qiáng)的方法調(diào)用被裝飾類中的同名方法
            liuDeHua.dance();
        }
    }
    

commons-io工具包

commons-io工具包概述

commons-io是apache開源基金組織提供的一組有關(guān)IO操作的類庫(kù),可以挺提高IO功能開發(fā)的效率。commons-io工具包提供了很多有關(guān)io操作的類,見下表:

功能描述
org.apache.commons.io 有關(guān)Streams、Readers、Writers、Files的工具類
org.apache.commons.io.input 輸入流相關(guān)的實(shí)現(xiàn)類,包含Reader和InputStream
org.apache.commons.io.output 輸出流相關(guān)的實(shí)現(xiàn)類,包含Writer和OutputStream
org.apache.commons.io.serialization 序列化相關(guān)的類

commons-io工具包 使用步驟

步驟:

  1. 下載commons-io相關(guān)jar包;http://commons.apache.org/proper/commons-io/
  2. 把commons-io-2.6.jar包復(fù)制到指定的Module的lib目錄中(必須在指定的Module的lib目錄下, lib目錄和src目錄為同級(jí)目錄)
  3. 將commons-io-2.6.jar加入到classpath中(IDEA中右鍵該工具包選擇Add as Libary表示添加到本模塊中作為工具庫(kù))

commons-io工具包常用API

  • commons-io提供了一個(gè)工具類 org.apache.commons.io.IOUtils,封裝了大量IO讀寫操作的代碼。其中有兩個(gè)常用方法:

    1. public static int copy(InputStream in, OutputStream out); 把input輸入流中的內(nèi)容拷貝到output輸
      出流中,返回拷貝的字節(jié)個(gè)數(shù)(適合文件大小為2GB以下)
    2. public static long copyLarge(InputStream in, OutputStream out);把input輸入流中的內(nèi)容拷貝到
      output輸出流中,返回拷貝的字節(jié)個(gè)數(shù)(適合文件大小為2GB以上)

    代碼演示

     public static void main(String[] args) throws Exception {
         // 文件路徑需要修改,改成自己文件的路徑
         File file = new File("src/test.txt");
         FileInputStream is = new FileInputStream(file);
         // 文件路徑需要修改
         File file1 = new File("src/test1.txt");
         FileOutputStream os = new FileOutputStream(file1);
         // 文件復(fù)制
         IOUtils.copy(is, os);
     }
    
  • commons-io還提供了一個(gè)工具類org.apache.commons.io.FileUtils,封裝了一些對(duì)文件操作的方法:

    1. public static void copyFileToDirectory(?nal File srcFile, ?nal File destFile) //復(fù)制文件到另外一個(gè)目錄
      下。
    2. public static void copyDirectoryToDirectory( ?le1 , ?le2 );//復(fù)制?le1目錄到?le2位置。

    代碼演示

    public static void main(String[] args) throws IOException {
            //1.將d:\\視頻.itcast文件復(fù)制到e:\\下
            FileUtils.copyFileToDirectory(new File("d:\\視頻.itcast"), new File("e:\\"));
            //2.將"d:\\多級(jí)目錄"復(fù)制到"e:\\"下。
            FileUtils.copyDirectoryToDirectory(new File("d:\\多級(jí)目錄"), new File("e:\\"));
        }
    

今日小結(jié)

1.緩沖流【重點(diǎn)】
字節(jié)緩沖流(BufferedOutputStream和BufferedInputStream),沒有特有方法,性能比普通流更高

字符緩沖流(BufferedWriter和BufferedReader),有特有方法,性能比普通流更高
  BufferedWriter: 
      public void newLine();
  BufferedReader:
      public String readLine();

2.轉(zhuǎn)換流【重點(diǎn)】
轉(zhuǎn)換輸出流: 可以指定編碼寫文件
OutputStreamWriter
public OutputStreamWriter(OutputStream out,String 指定的編碼);
轉(zhuǎn)換輸入流: 可以指定編碼讀文件
InputStreamReader
public InputStreamReader(InputStream in,String 指定的編碼);

3.序列化流【理解】
序列化流: 寫對(duì)象
ObjectOutputStream
public void writeObject(對(duì)象);//該對(duì)象的類必須實(shí)現(xiàn)java.io.Serializable接口
反序列化流: 讀對(duì)象
ObjectInputStream
public Object readObject();
4.打印流【理解】
PrintStream ps = new PrintStream(String path/File file/OutputStream out);
方法:
print(各種數(shù)據(jù)類型);
println(各種數(shù)據(jù)類型);

5.裝飾設(shè)計(jì)模式【理解】
步驟:
a.被裝飾類和裝飾類實(shí)現(xiàn)同一個(gè)接口
b.裝飾類內(nèi)部必須含有被裝飾類的引用
c.在裝飾類中對(duì)需要裝飾的方法進(jìn)行裝飾
d.在裝飾類中對(duì)不需要裝飾的方法調(diào)用原對(duì)象的方法

6.commons-io【重點(diǎn)】
IOUtils 復(fù)制文件(2G以上和2G以下)
FileUtils 復(fù)制文件和復(fù)制文件夾

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容