Java19-day10【标准输入输出流、字节字符打印流、对象序列化-反序列化流、serialVersionUID&transient、Properties】

   

目   录

01_集合到文件数据排序改进版

案例:集合到文件(数据排序改进版)

02_复制单级文件夹

案例:复制单级文件夹

03_复制多级文件夹

案例:复制多级文件夹

04_复制文件的异常处理

3.10、复制文件的异常处理

05_标准输入流

4.1、标准输入输出流

06_标准输出流

4.1、标准输入输出流

07_字节打印流

4.2、打印流

08_字符打印流

4.2、打印流

09_复制Java文件打印流改进版

案例:复制Java文件(打印流改进版)

10_对象序列化流

4.3、对象序列化流

11_对象反序列化流

4.3、对象序列化流

12_serialVersionUID&transient

4.3、对象序列化流

13_Properties作为Map集合的使用

4.4、Properties

14_Properties作为Map集合的特有方法

4.4、Properties

15_Properties和IO流相结合的方法

4.4、Properties

16_游戏次数

案例:游戏次数


01_集合到文件数据排序改进版

案例:集合到文件(数据排序改进版)

package com.itheima_07;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet;

public class TreeSetToFileDemo {
    public static void main(String[] args) throws IOException {
        // 2、创建TreeSet集合,通过比较器排序进行排序
        TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                //成绩总分从高到低
                int num = s2.getSum() - s1.getSum();
                //次要条件
                int num2 = num == 0 ? s1.getChinese() - s2.getChinese() : num;
                int num3 = num2 == 0 ? s1.getMath() - s2.getMath() : num2;
                int num4 = num3 == 0 ? s1.getName().compareTo(s2.getName()) : num3;
                return num4;
            }
        });

        // 3、键盘录入学生数据
        for (int i = 0; i < 5; i++) {
            Scanner sc = new Scanner(System.in);
            System.out.println("请录入第" + (i + 1) + "个学生信息:");
            System.out.println("姓名:");
            String name = sc.nextLine();
            System.out.println("语文成绩:");
            int chinese = sc.nextInt();
            System.out.println("数学成绩:");
            int math = sc.nextInt();
            System.out.println("英语成绩:");
            int english = sc.nextInt();

            // 4、创建学生对象,把键盘录入的数据对应赋值给学生对象的成员变量
            Student s = new Student();
            s.setName(name);
            s.setChinese(chinese);
            s.setMath(math);
            s.setEnglish(english);

            // 5、把学生对象添加到TreeSet集合
            ts.add(s);
        }

        // 6、创建字符缓冲输出流对象
        BufferedWriter bw = new BufferedWriter(new FileWriter("ts.txt"));

        // 7、遍历集合,得到每一个学生对象
        for (Student s : ts) {
            // 8、把学生对象的数据拼接成指定格式的字符串
            //格式:姓名,语文成绩,数学成绩,英语成绩
            StringBuilder sb = new StringBuilder();
            sb.append(s.getName()).append(",").append(s.getChinese()).append(",").
                    append(s.getMath()).append(",").append(s.getEnglish()).append(",").append(s.getSum());

            // 9、调用字符缓冲输出流对象的方法写数据
            bw.write(sb.toString());
            bw.newLine();
            bw.flush();
        }

        // 10、释放资源
        bw.close();
    }
}

02_复制单级文件夹

案例:复制单级文件夹

package com.itheima_08;

import java.io.*;

public class CopyFolderDemo {
    public static void main(String[] args) throws IOException {
        // 1:创建数据源目录File对象,路径是E:\\itcast
        File srcFolder = new File("E:\\itcast2");

        // 2:获取数据源目录File对象的名称(itcast)
        String srcFolderName = srcFolder.getName();

        // 3:创建目的地目录File对象,路径名是模块名+itcast组成(myCharStream\\itcast)
        //File destFolder = new File("myCharStream", srcFolderName);
        File destFolder = new File(srcFolderName);

        // 4:判断目的地目录对应的File是否存在,如果不存在,就创建
        if (!destFolder.exists()) {
            destFolder.mkdir();
        }

        // 5:获取数据源目录下所有文件的File数组
        File[] listFiles = srcFolder.listFiles();

        // 6:遍历File数组,得到每一个File对象,该File对象,其实就是数据源文件
        for (File srcFile : listFiles) {
            //数据源文件:E:\\itcast\\mn.jpg
            // 7:获取数据源文件File对象的名称(mn.jpg)
            String srcFileName = srcFile.getName();
            // 8:创建目的地文件File对象,路径名是目的地目录+mn.jpg组成(myCharStream\\itcast\\mn.jpg)
            File destFile = new File(destFolder, srcFileName);
            // 9:复制文件
            copyFile(srcFile, destFile);
        }
    }

    private static void copyFile(File srcFile, File destFile) throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile));

        byte[] bys = new byte[1024];
        int len;
        while ((len = bis.read(bys)) != -1) {
            bos.write(bys, 0, len);
        }

        bos.close();
        bis.close();
    }
}

03_复制多级文件夹

案例:复制多级文件夹

package com.itheima_08;

import java.io.*;

public class CopyFoldersDemo {
    public static void main(String[] args) throws IOException {
        //1、创建数据源File对象,路径是E:\\itcast
        File srcFile = new File("E:\\itcast");
        //2、创建目的地File对象,路径是F:\\
        File destFile = new File("F:\\");

        //3、写方法实现文件夹的复制,参数为数据源File对象和目的地File对象
        copyFolder(srcFile, destFile);
    }

    //复制文件夹
    private static void copyFolder(File srcFile, File destFile) throws IOException {
        //4、判断数据源File是否是目录
        if (srcFile.isDirectory()) {
            //A:在目的地下创建和数据源File名称一样的目录
            String srcFileName = srcFile.getName();
            File newFolder = new File(destFile, srcFileName); //F:\\itcast
            if (!newFolder.exists()) {
                newFolder.mkdir();
            }

            //B:获取数据源File下所有文件或者目录的File数组
            File[] fileArray = srcFile.listFiles();

            //C:遍历该File数组,得到每一个File对象
            for (File file : fileArray) {
                //D:把该File作为数据源File对象,递归调用复制文件夹的方法
                copyFolder(file, newFolder);
            }
        } else {
            //说明是文件,直接复制,用字节流
            File newFile = new File(destFile, srcFile.getName());
            copyFile(srcFile, newFile);
        }
    }

    //字节缓冲流复制文件
    private static void copyFile(File srcFile, File destFile) throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile));

        byte[] bys = new byte[1024];
        int len;
        while ((len = bis.read(bys)) != -1) {
            bos.write(bys, 0, len);
        }

        bos.close();
        bis.close();
    }

}

04_复制文件的异常处理

3.10、复制文件的异常处理

package com.itheima_09;

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

/*
    复制文件加入异常处理
 */
public class CopyFileDemo {
    public static void main(String[] args) {

    }

    //JDK9的改进方案
    private static void method4() throws IOException {
        FileReader fr = new FileReader("fr.txt");
        FileWriter fw = new FileWriter("fw.txt");
        try (fr; fw) {
            char[] chs = new char[1024];
            int len;
            while ((len = fr.read()) != -1) {
                fw.write(chs, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //JDK7的改进方案
    private static void method3() {
        try (FileReader fr = new FileReader("fr.txt");
             FileWriter fw = new FileWriter("fw.txt");) {
            char[] chs = new char[1024];
            int len;
            while ((len = fr.read()) != -1) {
                fw.write(chs, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //try...catch...finally 方法内部处理异常 比较复杂
    private static void method2() {
        FileReader fr = null;
        FileWriter fw = null;
        try {
            fr = new FileReader("fr.txt");
            fw = new FileWriter("fw.txt");

            char[] chs = new char[1024];
            int len;
            while ((len = fr.read()) != -1) {
                fw.write(chs, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fw != null) {
                try {
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fr != null) {
                try {
                    fr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    //抛出处理
    private static void method1() throws IOException {
        FileReader fr = new FileReader("fr.txt");
        FileWriter fw = new FileWriter("fw.txt");

        char[] chs = new char[1024];
        int len;
        while ((len = fr.read()) != -1) {
            fw.write(chs, 0, len);
        }

        fw.close();
        fr.close();
    }
}

05_标准输入流

   

4.1、标准输入输出流

System类中有两个静态的成员变量:

  • public static final InputStream in  :标准输入流。通常该流对应于键盘输入或由主机环境或用户指定的另一个输入源。
  • public static final PrintStream out:标准输出流。通常该流对应于显示输出或由主机环境或用户指定的另一个输出目标。

自己实现键盘录入数据:

  • BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

自己实现键盘录入数据太麻烦了,所以Java就提供了一个类供我们使用:

  • Scanner sc = new Scanner(System.in); // xxx.nextLine();   xxx.nextInt(); ...

06_标准输出流

4.1、标准输入输出流

System类中有两个静态的成员变量:

  • public static final InputStream in  :标准输入流。通常该流对应于键盘输入或由主机环境或用户指定的另一个输入源。
  • public static final PrintStream out:标准输出流。通常该流对应于显示输出或由主机环境或用户指定的另一个输出目标。

输出语句的本质:是一个标准的输出流。

  • PrintStream ps = System.out;
  • PrintStream类有的方法,System.out都可以使用。

 ...

07_字节打印流

4.2、打印流

打印流分类

  • 字节打印流:PrintStream
  • 字符打印流:PrintWriter

打印流的特点:

  • 只负责输出数据,不负责读取数据;
  • 永远不会抛出IOException;
  • 有自己的特有方法。

字节打印流

  • PrintStream(String fileName):使用指定的文件名创建新的打印流。
  • 使用继承父类的方法写数据,查看的时候会转码;使用自己的特有方法写数据,查看的数据原样输出。
  • 可以改变输出语句的目的地。

public static void setOut(PrintStream out):重新分配“标准”输出流

08_字符打印流

4.2、打印流

字符打印流PrintWriter的构造方法:

  

PrintWriter​(Writer out, boolean autoFlush):创建一个新的PrintWriter【实现自动刷新:autoFlush参数为true】

09_复制Java文件打印流改进版

案例:复制Java文件(打印流改进版)

10_对象序列化流

4.3、对象序列化流

对象序列化介绍

  • 对象序列化:就是将对象保存到磁盘中,或者在网络中传输对象。
  • 这种机制就是使用一个字节序列表示一个对象,该字节序列包含:对象的类型、对象的数据和对象中存储的属性等信息。
  • 字节序列写到文件之后,相当于文件中持久保存了一个对象的信息;
  • 反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化。

要实现序列化反序列化就要使用对象序列化流对象反序列化流

  • 对象序列化流: ObjectOutputStream
  • 对象反序列化流:ObjectInputStream

对象序列化流: ObjectOutputStream

  • 将Java对象的原始数据类型和图形写入OutputStream。可以使用ObjectInputStream读取(重构)对象。可以通过使用流的文件来实现对象的持久存储。如果流是网络套接字流,则可以在另一个主机上或另一个进程中重构对象。

构造方法:

  • ObjectOutputStream​(OutputStream out):创建一个写入指定的OutputStream的ObjectOutputStream

序列化对象的方法:

  • void writeObject​(Object obj):将指定的对象写入ObjectOutputStream

注意: 

  • 一个对象要想被序列化,该对象所属的类必须必须实现Serializable接口。
  • Serializable是一个标记接口,实现该接口,不需要重写任何方法。
  • NotSerializableException:抛出一个实例需要一个Serializable接口。 序列化运行时或实例的类可能会抛出此异常。
  • 类的序列化由实现java.io.Serializable接口的类启用。不实现此接口的类将不会使任何状态序列化或反序列化。

  

11_对象反序列化流

4.3、对象序列化流

对象反序列化流:ObjectInputStream

  • ObjectInputStream反序列化先前使用ObjectOutputStream编写的原始数据和对象。

构造方法:

  • ObjectInputStream​(InputStream in):创建从指定的InputStream读取的ObjectInputStream。

反序列化对象的方法:

  • Object readObject​():从ObjectInputStream读取一个对象。

12_serialVersionUID&transient

4.3、对象序列化流

用对象序列化流序列化了一个对象后,假如我们修改了对象所属的类文件,读取数据会不会出问题呢?

  • 会出问题,抛出InvalidClassException异常。

    java.io.InvalidClassException:
        当序列化运行时检测到类中的以下问题之一时抛出:
            类的串行版本与从流中读取的类描述符的类型不匹配(√)
            该类包含未知的数据类型
            该类没有可访问的无参数构造函数

    com.itheima_03.Student; local class incompatible:
    stream classdesc serialVersionUID = -3743788623620386195,
    local class serialVersionUID = -247282590948908173

如果出问题了,如何解决呢?

  • 重新序列化。给对象所属的类加一个值serialVersionUID:【private static final long serialVersionUID = 42L;】

如果一个对象中的某个成员变量的值不想被序列化,又该如何实现呢?

  • 给该成员变量加transient关键字修饰,该关键字标记的成员变量不参与序列化过程。【private transient int age;】

调用write()方法后,修改Student.java(添加toString()方法),调用read()方法:报错 java.io.InvalidClassException。修改Student.java文件后,序列化ID发生改变!序列化ID前后不一致,导致出错!!!

  

   

在Student.java文件中,增加“private static final long serialVersionUID = 42L; ”,调用write()方法,修改Student.java文件(注释掉toString()方法),调用read()方法:无报错!

如果一个对象中的某个成员变量的值不想被序列化,又该如何实现呢?

  • 给该成员变量加transient关键字修饰,该关键字标记的成员变量不参与序列化过程。【private transient int age;】

不想让外部知道Student对象的age变量 --> private transient int age; // 不参与序列化过程, age变量默认为0

13_Properties作为Map集合的使用

4.4、Properties

Properties介绍

  • 是一个Map体系的集合类。
  • Properties可以保存到流中或从流中加载。
  • 属性列表中的每个键及其对应的值都是一个字符串。

练习:Properties作为Map集合的使用。

Hashtable与Map用法一致。

 Properties不能有泛型!

14_Properties作为Map集合的特有方法

4.4、Properties

Properties作为集合的特有方法:

15_Properties和IO流相结合的方法

4.4、Properties

Properties和IO流相结合的方法:

16_游戏次数

案例:游戏次数

       

猜你喜欢

转载自blog.csdn.net/weixin_44949135/article/details/107968971