JavaSEday12緩衝流、轉換流、序列化流和打印流

day12_面向對象(緩衝流、轉換流、序列化流和打印流)
    一.緩衝流
        1.緩衝流的作用
            緩衝流也叫高效流,它是對普通流的增強,增強再性能方面
        2.緩衝流的分類
            字節輸入流 ——> 緩衝字節輸入流
            InputStream ——> BufferedInputStream
            字節輸出流 ——> 緩衝字節輸出流
            OutputStream ——> BufferedOutputStream
            字符輸入流 ——> 緩衝字符輸入流
            Reader ——> BufferedReader
            字符輸出流 ——> 緩衝字符輸出流
            Writer ——> BufferedWriter
        3.字節緩衝流的介紹和使用
            a.字節緩衝流的構造
                public BufferedInputStream(InputStream in);緩衝流創建需要普通流
                public BufferedOutputStream(OutputStream out);緩衝流創建需要普通流
            b.字節緩衝流的高效測試

public class BufferedStreamDemo {
    public static void main(String[] args) throws IOException {
        //調用
        long start = System.currentTimeMillis();
        copy03();
        long end = System.currentTimeMillis();
        System.out.println("耗時:" + (end - start) + "毫秒...");
    }
    //定義方法:複製文件
    //使用緩衝流
    //定義方法:複製文件
    //使用緩衝流 耗時:169毫秒...
    public static void copy03()throws IOException {
        //1.緩衝字節輸入流
//        FileInputStream fis = new FileInputStream("1.avi");
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("1.avi"));
        //2.緩衝字節輸出流
//        FileOutputStream fos = new FileOutputStream("copy.avi");
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.avi"));
        //3.複製,採用字節數組
        byte[] bs = new byte[1024 * 100];
        int len = 0;
        while ((len = bis.read(bs)) != -1) {
            bos.write(bs, 0, len);
        }
        //4.釋放資源
        bos.close();
//        fos.close();
        bis.close();
//        fis.close();
    }

    //定義方法:複製文件
    //使用緩衝流 耗時:4111毫秒...
    public static void copy02()throws IOException {
        //1.緩衝字節輸入流
//        FileInputStream fis = new FileInputStream("1.avi");
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("1.avi"));
        //2.緩衝字節輸出流
//        FileOutputStream fos = new FileOutputStream("copy.avi");
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.avi"));
        //3.複製
        int b = 0;
        while ((b = bis.read()) != -1) {
            bos.write(b);
        }
        //4.釋放資源
        bos.close();
//        fos.close();
        bis.close();
//        fis.close();
    }


    //定義方法:複製文件
    //使用普通流
    public static void copy01() throws IOException {
        //1.字節輸入流
        FileInputStream fis = new FileInputStream("1.avi");
        //2.字節輸出流
        FileOutputStream fos = new FileOutputStream("copy.avi");
        //3.一個一個字節慢慢來
        int b = 0;
        while ((b = fis.read()) != -1) {
            fos.write(b);
        }
        //4.關閉
        fos.close();
        fis.close();
    }
}


        4.字符緩衝流的介紹和使用
            a.字符緩衝流的構造
                public BufferedReader(Reader r); 創建緩衝字符流需要普通字符流
                public BufferedWriter(Writer w);創建緩衝字符流需要普通字符流
            b.字符緩衝流的2個特有方法
                BufferedReader緩衝字符輸入流
                    public String readLine(); 一次讀取一行

public class BufferedReaderDemo {
    public static void main(String[] args) throws Exception {
        //1.創建BufferedReader對象
        BufferedReader br = new BufferedReader(new FileReader("1.txt"));

        //2.讀取數據
//        String line = br.readLine();
//        System.out.println(line);
        //一次讀取一行的標準循環代碼
        String line = "";
        /**
         * (line = br.readLine()) != null
         * a.先讀一行
         * b.賦值  line = 一行的內容
         * c.判斷  line != null
         */
        while ((line = br.readLine()) != null) {
            System.out.println(line);
        }
        //3.釋放資源
        br.close();
    }
}


BufferedWriter緩衝字符輸出流
    public void newLine(); 寫一個跨平臺的換行符

public class BufferedWriterDemo {
    public static void main(String[] args) throws IOException {
        //1.創建一個BufferedWriter對象
        BufferedWriter bw = new BufferedWriter(new FileWriter("1.txt"));
        //2.寫數據
        for (int i = 0; i < 10; i++) {
            bw.write("java");
            //bw.write("\r\n"); //Java是跨平臺  
            bw.newLine();//寫一個跨平臺換行符   
        }
        //3.釋放資源
        bw.close();
    }
}

        5.綜合練習:文本排序
            將一個文件中的內容讀取,根據每一行的編號,從小到大寫到另一個文本文件中

public class BufferedTestDemo {
    public static void main(String[] args) throws Exception {
//        綜合練習:文本排序
//                將一個文件中的內容讀取,根據每一行的編號,從小到大寫到另外一個文本文件中
        //1.將原文本一行一行讀取出來,保存到集合中
        ArrayList<String> lines = new ArrayList<String>();
        //讀取文本
        BufferedReader br = new BufferedReader(new FileReader("csb.txt"));
        //循環
        String line = "";
        while ((line = br.readLine()) != null) {
            //保存到集合
            lines.add(line);
        }
        //釋放資源
        br.close();
        //3.對集合中文本進行排序
        Collections.sort(lines, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                //口訣:升序 前 - 後
                return o1.charAt(0) - o2.charAt(0);
            }
        });
        //4.寫到另外一個文本中
        BufferedWriter bw = new BufferedWriter(new FileWriter("csb02.txt"));
        for (String str : lines) {
            bw.write(str);
            //換行
            bw.newLine();
        }
        bw.close();
    }
}


    二.轉換流*******************
        1.字符集
            是一個平臺所能支持的所有字符的集合(文字、符號、圖形、數字)(編碼表等於字符集加碼值)
        2.字符編碼(編碼和解碼)
            就是指每一個字符和對應碼值的轉換規則
            編碼:把字符轉成對應的碼值 比如:a --> 97
            解碼:把碼值轉成對應的字符 比如:97 --> a

        擴展:
            常見的字符集和字符編碼
            a.ascii字符集(美國標準信息交換代碼) 包含英文字母,英文標點,阿拉伯數字(128個)
            其對應的字符編碼ascii編碼,在ascii編碼中所有的字符只佔一個字節
            b.GBXXXX字符集
                GB2312字符集 含有大概7000多個漢字(簡體常用漢字)
                GBK字符集 含有大概兩萬多個漢字(簡體和繁體漢字以及日韓漢字)
                GB18030字符集 含有大概70000多個漢字(目前還沒有啓用)
            GBXXXX字符集對應的字符編碼稱爲GBK編碼,在GBK編碼中一箇中文佔2個字節
            c.Unicode字符集
                萬國字符集(全球幾乎所有國家的字符都在此字符集中)
                Unicode字符集對應的字符編碼稱爲UTF-8編碼,UTF-16編碼,UTF-32編碼
                在UTF-8編碼中一箇中文佔3個字節
            d.ISO-8859-1字符集
                拉丁字符集(西歐國家)
                ISO-8859-1字符集採用ISO-8859-1字符編碼,每一個字符佔一個字節(二進制都是1開頭,表示負數,ascii碼值中二進制都是0開頭的,故不衝突)
                以後我們的服務器(Tomcat7.0)默認採用就是ISO-8859-1,我們需要手動改爲GBK或者UTF-8
        3.編碼引出的問題
        總結:只要是亂碼,99%的情況下都是由編碼不一致引起的
            比如文本是GBK,讀取時,IDEA默認使用的是UTF-8,所以出現亂碼

public class LuanMaDemo {
    public static void main(String[] args) throws Exception {
        //1.讀取文件 2.txt(記事本默認是GBK編碼)
        FileReader fr = new FileReader("2.txt"); //IDEA中讀取中時,默認UTF-8
        //2.讀取一個字符
        int read = fr.read();
        System.out.println((char) read);
        //3.釋放資源
        fr.close();
    }
}


        4.使用轉換流InputStreamReader解決中文問題
            InputStreamReader extends Reader
            1.構造方法
            public InputStreamReader(InputStream in, String charsetName); 指定編碼
            public InputStreamReader(InputStream in); 默認和IDEA一樣(UTF-8)
            2.使用InputStreamReader讀取不同編碼的文件(代碼演示)

public class InputStreamReaderDemo {
    public static void main(String[] args) throws Exception {
        //1.創建一個InputStreamReader對象
//        InputStreamReader isr = new InputStreamReader(new FileInputStream("gbk.txt"), "gbk");
        InputStreamReader isr = new InputStreamReader(new FileInputStream("utf8.txt"), "gbk");
        //2.讀
        int read = isr.read();
        System.out.println((char) read);

        read = isr.read();
        System.out.println((char) read);

        read = isr.read();
        System.out.println((char) read);
        //2.釋放資源
        isr.close();
    }
}

        5.使用轉換流OutputStreamWriter寫中文
            OutputStreamWriter extends Writer
            1.構造方法
            public OutputStreamWriter(InputStream in, String charsetName);   指定編碼
            public OutputStreamWriter(InputStream in); 默認和IDEA一樣UTF-8編碼

public static void main(String[] args) throws Exception {
        //1.寫文件
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("utf8.txt"),"UTF-8");
//        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("gbk.txt"),"gbk");
        //2.寫數據
        osw.write('你');
        osw.write('好');
        //3.釋放資源
        osw.close();
    }
}

        6.練習:轉換文件編碼****************
            練習:將GBK編碼的文件,轉換爲UTF-8編碼的文本文件

public class TestDemo {
    public static void main(String[] args) throws Exception {
//        6.練習:轉換文件編碼**********************
//        需求:將GBK編碼的文本文件,轉換爲UTF-8編碼的文本文件。
        //1.創建一個轉換輸入流
        InputStreamReader isr = new InputStreamReader(new FileInputStream("test_gbk.txt"),"gbk");
        //2.創建一個轉換輸出流
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("test_utf.txt"), "utf-8");
        //3.一邊讀 一邊寫
        int ch = 0;
        while ((ch = isr.read()) != -1) {
            osw.write(ch);
        }
        //4.釋放資源
        osw.close();
        isr.close();
    }
}


    三.序列化流
        1.什麼是序列化流
            字符流:以字符爲單位操作數據
            字節流:以字節爲單位操作數據
            序列化流:也叫對象流,以對象爲單位操作數據            序列化流:對象的輸出流,寫對象
                ObjectOutputStream
            反序列化流:對象的輸入流,讀對象
                ObjectInputStream
        2.ObjectOutputStream的介紹和使用
            a.構造方法
                public ObjectOutputStream(OutputStream out);
                創建序列化流需要普通的字節輸出流
            b.序列化操作的前提
                被序列化的對象必須使用java.io.Serializable接口
            c.序列化操作(代碼演示)

public class Dog implements Serializable{
    int age;
    String name;
    int legs;

    public Dog() {
    }

    public Dog(int age, String name, int legs) {
        this.age = age;
        this.name = name;
        this.legs = legs;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", legs=" + legs +
                '}';
    }
}
public class ObjectStreamDemo {
    public static void main(String[] args) throws IOException {
        //1.創建一個ObjectOutputStream對象
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("1.txt"));
        //3.寫對象
        //NotSerializableException
        Dog d = new Dog(2, "旺財", 3);
        oos.writeObject(d);

        //3.釋放資源
        oos.close();
    }
}

        3.ObjectInputStream的介紹和使用
            ObjectinputStream對象的輸入流,也叫反序列化流
            a.構造方法
                public ObjectInputStream(InputStream in); 創建反序列化時需要普通的字節輸入流
            b.反序列操作(正常演示)

public class ObjectStreamDemo01 {
    public static void main(String[] args) throws Exception {
        //1.創建ObjectInputStream對象
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("1.txt"));
        //2.讀對象
        Object obj = ois.readObject();
        System.out.println(obj);
        //3.釋放資源
        ois.close();
    }
}

            c.反序列化操作的兩種錯誤演示
                i.InvalidClassException 無效類異常
                    原因:序列化之後,反序列化之前,修改了類的源碼
                ii.ClassNotFoundException 找不到類異常
                    原因:序列化之後,反序列化之前,直接刪除類
            d.序列化流通過對比類的序列化版本號,判斷類是否有效的
                每一個實現java.io.Serializable接口會自動生成一個版本號,當內容發生改變之後,版本號會重新計算,生成新的版本號,所以,反序列化時對比流中對象的版本號和本地類的對象的版本號,不一致就拋出異常            e.序列化版本號允許程序員自己管理,但是版本自己管理必須是以下格式:
            public static final long seriralVersionUID = 值;
            f.關鍵字: transient (''括起來表示默認值)
                transient關鍵字修飾成員變量
                作用:被transient修飾的成員和以前沒有任何區別!!!
                當序列化流序列化該對象時,忽略有transient標記的成員變量
        4.;練習:如果需要序列化多個對象怎麼操作?********************
            解決方案:創建一個結合,把多個對象保存到這個集合對象中

public class ObjectStreamTestDemo {
    public static void main(String[] args) throws Exception {
        readArrayList();
    }

    public static void readArrayList() throws Exception {
        //1.創建反序列化流
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("dogs.txt"));
        //2.讀對象
        ArrayList<Dog> dogs = (ArrayList<Dog>) ois.readObject();
        for (Dog dog : dogs) {
            System.out.println(dog);
        }
        //3.釋放資源
        ois.close();
    }
    public static void writeArrayList() throws IOException {
        //1.有多個對象
        Dog d1 = new Dog(1, "旺1財", 2);
        Dog d2 = new Dog(2, "旺2財", 3);
        Dog d3 = new Dog(3, "旺3財", 4);
        Dog d4 = new Dog(4, "旺4財", 5);
        //2.要將這些對象保存到集合中
        ArrayList<Dog> dogs = new ArrayList<Dog>();
        Collections.addAll(dogs, d1, d2, d3, d4);
        //3.只要序列化這個集合對象
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("dogs.txt"));
        //4.寫對象
        oos.writeObject(dogs);
        //5.釋放資源
        oos.close();
    }
}

        
    四.打印流
        1.打印流PrintStream的介紹
            a.所見即所得
            b.打印流不會拋出IOException
        2.PrintStream的構造和常用方法
            構造方法:
                public printStream(String pathname);
                public printStream(File file);
                public publicStream(OutputStream out);
            成員方法:
                public void print(任意數據類型); 打印數據但是不換行
                public void println(任意數據類型); 打印數據且換行

public class PrintStreamDemo {
    public static void main(String[] args) throws Exception {
        //1.創建一個打印流
        PrintStream ps = new PrintStream("print.txt");
//        PrintStream ps = new PrintStream(new File("print.txt"));
//        PrintStream ps = new PrintStream(new FileOutputStream("print.txt"));
        //2.打印  (特點:所見即所得)
//        ps.print('a');
//        ps.print(97);
//        ps.print("java");
//        ps.print(3.14);
//        ps.print(true);
//        ps.print(false);

        ps.println('a');
        ps.println(97);
        ps.println("java");
        ps.println(3.14);
        ps.println(true);
        ps.println(false);
        
        //2.釋放資源
        ps.close();
    }
}

        3.擴展_修改打印流的流向
            打印流:System.out.println();  之前一直在用

public class PrintStreamDemo02 {
    public static void main(String[] args) throws Exception {
//        PrintStream ps = System.out;
        System.out.println("HelloWorld");
        System.out.println("HelloWorld");
        System.out.println("HelloWorld");
        System.out.println("HelloWorld");
        //修改System.out這個打印的方向
        PrintStream ps = new PrintStream("111.txt");
//        System.out = ps;
        System.setOut(ps);
        //測試
        System.out.println("Java");
        System.out.println("Java");
        System.out.println("Java");
        System.out.println("Java");
        System.out.println("Java");
    }
}


    
總結:
        -[] 能夠使用字節緩衝流中流讀取數據到程序
            BufferedInputStream
        -[] 能夠使用字節緩衝流寫出數據到文件
            BufferedOutputStream
        -[] 能夠明確字符緩衝流的作用和基本用法
        -[] 能夠使用緩衝流的特殊功能
            BufferedReader
                public String readLine();
            BufferedWriter
                public void newLine();
        -[] 能夠闡述編碼表的意義
        -[] 能夠使用轉換流讀取指定編碼的文本文件
            InputStreamReader FileReader
        -[] 能夠使用轉換流寫入指定編碼的文本文件
            OutputStreamWriter FileWriter
        -[] 能夠使用序列化流寫出對象到文件
            ObjectOutputStream
        -[] 能夠使用反序列化流讀取文件到程序中
            ObjectInputStream

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章