Java-进阶-day10-IO流_03

Java进阶-day08-IO流_01

今日内容

  • IO流案例
  • 标准流
  • 打印流
  • 对象流
  • Properties

一. IO流案例

  • 集合到文件数据排序改进版
  • 案例需求
    • 键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩)。要求按照成绩总分从高到低写入文本文件
    • 格式:姓名,语文成绩,数学成绩,英语成绩 举例:林青霞,98,99,100
  • 分析步骤
    1. 定义学生类
    2. 创建TreeSet集合,通过比较器排序进行排序
    3. 键盘录入学生数据
    4. 创建学生对象,把键盘录入的数据对应赋值给学生对象的成员变量
    5. 把学生对象添加到TreeSet集合
    6. 创建字符缓冲输出流对象
    7. 遍历集合,得到每一个学生对象
    8. 把学生对象的数据拼接成指定格式的字符串
    9. 调用字符缓冲输出流对象的方法写数据
    10. 释放资源
public class TreeSetToFileDemo {
    public static void main(String[] args) throws IOException {
        //创建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;
            }
        });

        //键盘录入学生数据
        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();

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

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

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

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

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

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

  • 复制单级文件夹
  • 案例需求:
    • 把“E:\itcast”这个文件夹复制到模块目录下
  • 分析步骤
    1. 创建数据源目录File对象,路径是E:\itcast
    2. 获取数据源目录File对象的名称
    3. 创建目的地目录File对象,路径由(模块名+第2步获取的名称)组成
    4. 判断第3步创建的File是否存在,如果不存在,就创建
    5. 获取数据源目录下所有文件的File数组
    6. 遍历File数组,得到每一个File对象,该File对象,其实就是数据源文件
    7. 获取数据源文件File对象的名称
    8. 创建目的地文件File对象,路径由(目的地目录+第7步获取的名称)组成
    9. 复制文件
    10. 由于不清楚数据源目录下的文件都是什么类型的,所以采用字节流复制文件采用参数为File的构造方法
/*
    需求:
        把E:\\itcast 这个文件夹复制到模块目录下

    思路:
        1:创建数据源目录File对象,路径是E:\\itcast
        2:获取数据源目录File对象的名称(itcast)
        3:创建目的地目录File对象,路径名是模块名+itcast组成(myCharStream\\itcast)
        4:判断目的地目录对应的File是否存在,如果不存在,就创建
        5:获取数据源目录下所有文件的File数组
        6:遍历File数组,得到每一个File对象,该File对象,其实就是数据源文件
            数据源文件:E:\\itcast\\mn.jpg
        7:获取数据源文件File对象的名称(mn.jpg)
        8:创建目的地文件File对象,路径名是目的地目录+mn.jpg组成(myCharStream\\itcast\\mn.jpg)
        9:复制文件
            由于文件不仅仅是文本文件,还有图片,视频等文件,所以采用字节流复制文件
 */
public class CopyFolderDemo {
    public static void main(String[] args) throws IOException {
        //创建数据源目录File对象,路径是E:\\itcast
        File srcFolder = new File("D:\\Youku\\唐唐说电影 第一季");

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

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

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

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

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

    private static void copyFile(File destFolder, File srcFile) throws IOException {
        //复制文件
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
        // new File(destFolder,srcFile.getName()
        // day10_code\唐唐说电影 第一季\3个80岁老头抢银行 竟然为泡妞 最年迈的劫匪-_高清
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File(destFolder,srcFile.getName())));

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

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

  • 复制多级文件夹
  • 案例需求

    • 把“E:\itcast”这个文件夹复制到 F盘目录下
  • 分析步骤

    1. 创建数据源File对象,路径是E:\itcast
    2. 创建目的地File对象,路径是F:\
    3. 写方法实现文件夹的复制,参数为数据源File对象和目的地File对象
    4. 判断数据源File是否是文件
  • 是文件:直接复制,用字节流

  • 不是文件:

    • 在目的地下创建该目录
    • 遍历获取该目录下的所有文件的File数组,得到每一个File对象
    • 回到3继续(递归)
public class CopyFile {
    public static void main(String[] args) throws IOException {
        // 数据源 E:\教学视频\第二阶段\day10\案例
        File srcFile = new File("E:\\教学视频\\第二阶段\\day10\\案例");
        // 目的地 D:\\
        File destFile = new File("D:\\");

        CopyFolder(srcFile, destFile);
    }

    private static void CopyFolder(File srcFile, File destFile) throws IOException {

        // 判断 源目录 是否是一个文件夹

        if (srcFile.isDirectory()) {
            // 创建文件夹,在目的地,还需要在拼接路径
            // D:\案例\myCharStream
            File newFile = new File(destFile, srcFile.getName());
            // 判断newFile是否是存在,如果不存在就创建文件夹
            if (!newFile.exists()) {
                newFile.mkdirs();
            }

            // 获取源目录下的所有的文件或文件夹
            File[] files = srcFile.listFiles();
            for (File file : files) {
                // 如果是文件,直接复制
                if (file.isFile()) {
                    // 使用字节缓冲流复制文件
                    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
                    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File(newFile,file.getName())));

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

                    // 释放资源
                    bos.close();
                    bis.close();

                }else if(file.isDirectory()){
                    // 如果是文件夹,递归调用CopyFolder
                    CopyFolder(file,newFile);
                }
            }
        }
    }
}

二.IO特殊操作流

标准流

  • 总结:

    • 其实就是我们常用的 System.in 和 System.out 这两个
  • System类的类字段

    • err : 标准的错误流
    • in : 标准的输入流 : 数据的来源? 键盘录入 ,经常使用在键盘录入数据
    • out : 标准的输出流 PrintStream 输出的目的是控制台
public class SystemInDemo {
    public static void main(String[] args) throws IOException {

        System.err.println("这是标准的错误流!!!!!");

        //public static final InputStream in:标准输入流
//        InputStream is = System.in;

//        int by;
//        while ((by=is.read())!=-1) {
//            System.out.print((char)by);
//        }

        //如何把字节流转换为字符流?用转换流
//        InputStreamReader isr = new InputStreamReader(is);
//        //使用字符流能不能够实现一次读取一行数据呢?可以
//        //但是,一次读取一行数据的方法是字符缓冲输入流的特有方法
//        BufferedReader br = new BufferedReader(isr);

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


        System.out.println("请输入一个字符串:");
        String line = br.readLine();
        System.out.println("你输入的字符串是:" + line);

        System.out.println("请输入一个整数:");
        int i = Integer.parseInt(br.readLine());
        System.out.println("你输入的整数是:" + i);
        //
        // //自己实现键盘录入数据太麻烦了,所以Java就提供了一个类供我们使用
        Scanner sc = new Scanner(System.in);
    }
}

打印流

  • PrintStream 字节打印流
  • PrintStream特点:
    • 1.只负责数据的输出,不负责数据的读取
    • 2.与其他输出流不同,PrintStream 永远不会抛出 IOException
    • 3.有特有的方法,print,println
      • void print(任意类型的值)
      • void println(任意类型的值并换行)
    • 构造方法:
      • PrintStream(File file):输出的目的地是一个文件
      • PrintStream(OutputStream out):输出的目的地是一个字节输出流
      • PrintStream(String fileName) :输出的目的地是一个文件路径

PrintWriter:

  • PrintWriter 字符打印流

  • 打印流的特点

    • 自动换行 println()
    • 不能输出字节 可以输出字节以外的内容
    • 必须是通过配置 自动刷新 (println,printf,format)
      boolean autoFlush: true 自动刷新 false,不自动刷新
    • 包装流本身没有写出功能
    • 将字节输出流转换字符输出流
  • PrintWriter特有方法和构造方法

    • a:PrintWriter构造方法
      • PrintWriter(String fileName) : 指定文件的名称并创建PrintWriter对象
      • PrintWriter(Writer out, boolean autoFlush) : 根据字符输出流,并是否开启自动刷新 创建PrintWriter对象
    • b:PrintWriter特有的方法
      • void write(String s): 写一个字符串
      • void print(String s): 输出字符串, 没有换行
      • void println(String s)(掌握): 输出字符串并换行. 如果启动了自动刷新, 则会执行自动刷新写入数据
      • void printf(Locale l, String format, Object… args): 使用指定格式字符串和参数将格式化的字符串写入输出流. 如果启动了自动刷新, 则会执行自动刷新写入数据
      • void format(Locale l, String format, Object… args): 使用指定格式字符串和参数将格式化的字符串写入输出流. 如果启动了自动刷新, 则会执行自动刷新写入数据
/*
    字符打印流的构造方法:
        PrintWriter​(String fileName) :使用指定的文件名创建一个新的PrintWriter,而不需要自动执行行刷新

        PrintWriter​(Writer out, boolean autoFlush):创建一个新的PrintWriter
            out:字符输出流
            autoFlush: 一个布尔值,如果为真,则println , printf ,或format方法将刷新输出缓冲区
 */
public class PrintWriterDemo {
    public static void main(String[] args) throws IOException {
        //PrintWriter​(String fileName) :使用指定的文件名创建一个新的PrintWriter,而不需要自动执行行刷新
//        PrintWriter pw = new PrintWriter("myOtherStream\\pw.txt");

//        pw.write("hello");
//        pw.write("\r\n");
//        pw.flush();
//        pw.write("world");
//        pw.write("\r\n");
//        pw.flush();

//        pw.println("hello");
        /*
            pw.write("hello");
            pw.write("\r\n");
         */
//        pw.flush();
//        pw.println("world");
//        pw.flush();

        //PrintWriter​(Writer out, boolean autoFlush):创建一个新的PrintWriter
        PrintWriter pw = new PrintWriter(new FileWriter("myOtherStream\\pw.txt"),true);
//        PrintWriter pw = new PrintWriter(new FileWriter("myOtherStream\\pw.txt"),false);

        pw.println("hello");
        /*
            pw.write("hello");
            pw.write("\r\n");
            pw.flush();
         */
        pw.println("world");

        pw.close();
    }
}

  • 复制Java文件打印流改进版
  • 案例需求
    • 把模块目录下的PrintStreamDemo.java 复制到模块目录下的 Copy.java
  • 分析步骤
    • 根据数据源创建字符输入流对象
    • 根据目的地创建字符输出流对象
    • 读写数据,复制文件
    • 释放资源
	public class CopyFile {
    public static void main(String[] args) throws IOException {
        // 数据源 day10_code\PrintStreamDemo.java
        BufferedReader br = new BufferedReader(new FileReader(new File("day10_code\\PrintStreamDemo.java")));
        // 目的地 day10_code\copy.java
        PrintWriter pw = new PrintWriter(new FileWriter(new File("day10_code\\copy.java")),true);

        String line;
        while ((line = br.readLine()) != null) {
            pw.println(line);
        }

        // pw.close();
        br.close();
    }
}

对象流

  • 对象的序列化流_ObjectOutputStream
  • 总结:
    • ObjectOutputStream的作用:

    • 构造方法:
      ObjectOutputStream(OutputStream out) 创建写入指定 OutputStream 的 ObjectOutputStream。

    • 成员方法:
      void writeObject(Object obj) 将指定的对象写入 ObjectOutputStream。

    • 使用步骤:

    • 1.创建ObjectOutputStream对象,构造方法中传递字节输出流

    • 2.使用ObjectOutputStream对象中的方法writeObject,把对象写入到文件中

    • 3.释放资源

public class ObjectOutputStreamDemo01 {
    public static void main(String[] args) throws IOException {
        // 创建对象 ObjectOutputStream
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("p.txt"));

        // 写数据
        // 创建Person对象
        Person p = new Person("张三", 13);
        oos.writeObject(p);

        // 释放资源
        oos.close();
    }
}

public class Person implements Serializable {
	// ....
}
  • 对象的反序列化流_ObjectInputStream
  • 总结:
    • ObjectInputStream:对象的序列化流
      作用:

    • 构造方法:

      • ObjectInputStream(InputStream in):创建从指定 InputStream 读取的 ObjectInputStream。
    • 成员方法:

      • Object readObject():从 ObjectInputStream 读取对象。
    • 使用步骤:

      • 1.创建 ObjectInputStream 对象,构造方法中传递字节输入流
      • 2.使用 ObjectInputStream 对象中的方法 readObject() 读取保存对象的文件
      • 3.释放资源
      • 4.使用读取出来的对象(打印)
 public static void main(String[] args) {
 	public static void main(String[] args) throws IOException, ClassNotFoundException {
        // method();
        // 反序列化
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("p.txt"));
        // 读取数据
        Object obj = ois.readObject();
        System.out.println(obj);
	}
}

#Properties集合

  • A:Properties 概述
  • B:Properties 作用
  • C:Properties 构造方法和成员方法
  • 总结:
    • A:概述

      • 在流中或从流中加载数据的
      • 将集合中的内容,进行持久化的
    • B:作用

      • 经常会用于简单的配置文件

      • 特点:

        • 默认数据的类型是String类型的
      • 注意事项:

        • 创建Properties集合对象的时候,不要加泛型,它根本就不是一个泛型类
    • C:构造方法和成员方法

      • a:构造方法
        • Properties Properties():
      • b:成员方法
        • String getProperty(String key) (重点掌握):
        • String getProperty(String key, String defaultValue):
        • void setProperty(String key, String value) (重点掌握):
        • Set stringPropertyNames() 返回此属性列表中的键集,其中该键及其对应值是字符串,此方法相当于Map集合中的keySet方法
/*
    Properties作为集合的特有方法:
        Object setProperty(String key, String value):设置集合的键和值,都是String类型,底层调用Hashtable方法put
        String getProperty(String key):使用此属性列表中指定的键搜索属性
        Set stringPropertyNames():从该属性列表中返回一个不可修改的键集,其中键及其对应的值是字符串
 */
public class PropertiesDemo02 {
    public static void main(String[] args) {
        //创建集合对象
        Properties prop = new Properties();

        //Object setProperty(String key, String value):设置集合的键和值,都是String类型,底层调用Hashtable方法put
        prop.setProperty("itheima001", "林青霞");
        /*
            Object setProperty(String key, String value) {
                return put(key, value);
            }

            Object put(Object key, Object value) {
                return map.put(key, value);
            }
         */
        prop.setProperty("itheima002", "张曼玉");
        prop.setProperty("itheima003", "王祖贤");

        //String getProperty(String key):使用此属性列表中指定的键搜索属性
//        System.out.println(prop.getProperty("itheima001"));
       System.out.println(prop.getProperty("itheima0011","默认值"));

//        System.out.println(prop);

        //Set stringPropertyNames():从该属性列表中返回一个不可修改的键集,其中键及其对应的值是字符串
        Set<String> names = prop.stringPropertyNames();
        for (String key : names) {
//            System.out.println(key);
            String value = prop.getProperty(key);
            System.out.println(key + "," + value);
        }
    }
}

Properties和IO流结合的功能

  • 常用方法

    • void load(InputStream in): 将文件内容加载到properties集合中
    • void load(Reader reader): 将文件内容加载到properties集合中
    • void store(Writer writer, String comments): 将properties集合中的内容写入到文件中,并添加文件的描述
    • void store(OutputStream out, String comments):将properties集合中的内容写入到文件中,并添加文件的描述
  • 常用 Propertis的读写操作步骤

    • 写出到文件

      • 1.创建Properties集合对象,添加数据
      • 2.创建字节输出流/字符输出流对象,构造方法中绑定要输出的目的地
      • 3.使用Properties集合中的方法store,把集合中的临时数据,持久化写入到硬盘中存储
      • 4.释放资源
    • 从文件读取

      • 1.创建Properties集合对象
      • 2.使用Properties集合对象中的方法load读取保存键值对的文件
      • 3.遍历Properties集合
    • 注意:

      • 1.存储键值对的文件中,键与值默认的连接符号可以使用=,空格(其他符号)
      • 2.存储键值对的文件中,可以使用#进行注释,被注释的键值对不会再被读取
      • 3.存储键值对的文件中,键与值默认都是字符串,不用再加引号

private static void myLoad() throws IOException {
    Properties prop = new Properties();
    //void load(Reader reader):
    FileReader fr = new FileReader("day10_code\\names.properties");
    prop.load(fr);
    fr.close();

    String itheima001 = prop.getProperty("itheima001");
    String itheima002 = prop.getProperty("itheima002");
    System.out.println(itheima001);
    System.out.println(itheima002);
}

  * 3.遍历Properties集合

    * 注意:
       * 1.存储键值对的文件中,键与值默认的连接符号可以使用=,空格(其他符号)
       * 2.存储键值对的文件中,可以使用#进行注释,被注释的键值对不会再被读取
       * 3.存储键值对的文件中,键与值默认都是字符串,不用再加引号

```java

private static void myLoad() throws IOException {
    Properties prop = new Properties();
    //void load(Reader reader):
    FileReader fr = new FileReader("day10_code\\names.properties");
    prop.load(fr);
    fr.close();

    String itheima001 = prop.getProperty("itheima001");
    String itheima002 = prop.getProperty("itheima002");
    System.out.println(itheima001);
    System.out.println(itheima002);
}

你可能感兴趣的:(Java进阶)