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

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