java进阶 - IO流(几个特殊流的介绍)

案例

  1. 案例1:将集合中的对象排序之后存储到文件中。选择TreeSet。
package com.jxufe_ldl.selfstudy;

public class Student {
    private String name;
    private int chenise;
    private int math;
    private int enghish;

    public Student() {
    }

    public Student(String name, int chenise, int math, int enghish) {
        this.name = name;
        this.chenise = chenise;
        this.math = math;
        this.enghish = enghish;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getChenise() {
        return chenise;
    }

    public void setChenise(int chenise) {
        this.chenise = chenise;
    }

    public int getMath() {
        return math;
    }

    public void setMath(int math) {
        this.math = math;
    }

    public int getEnghish() {
        return enghish;
    }

    public void setEnghish(int enghish) {
        this.enghish = enghish;
    }

    public int getSun() {
        return chenise + math + enghish;
    }
}

package com.jxufe_ldl.selfstudy;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;

/*
    从键盘输入5个学生的信息,保存到集合,再写入到文件
    格式:姓名,语文成绩,数学成绩,英语成绩
 */
public class ListToFile {
    public static void main(String[] args) throws IOException {
        // 创建TreeSet集合对象
        Set<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                // 主要条件
                int num = s2.getSun() - s1.getSun();

                // 次要条件
                int num2 = num == 0? s2.getChenise() - s1.getChenise() : num;
                int num3 = num2 == 0? s2.getMath() - s1.getMath() : num2;
                int num4 = num3 == 0 ? s1.getName().compareTo(s1.getName()) :num3;
                return num4;
            }
        });

        // 键盘录入5个学生成绩
        Scanner sc = new Scanner(System.in);
        System.out.println("请录入5个学生成绩:");
        for (int i = 0; i < 5; i++) {
            System.out.println("请输入第"+(i+1)+"学生姓名:");
            String name = sc.next();

            System.out.println("请输入语文成绩:");
            int chenise = sc.nextInt();

            System.out.println("请输入数学成绩:");
            int math = sc.nextInt();

            System.out.println("请输入英语成绩:");
            int enghtis = sc.nextInt();

            // 创建学生对象
            Student stu = new Student(name, chenise, math, enghtis);
            // 添加到集合
            ts.add(stu);
        }

        // 创建字符缓冲输出流对象
        BufferedWriter bw = new BufferedWriter(new FileWriter("day10//java//student.txt"));

        // 遍历集合,并写数据
        for (Student stu : ts) {
            // 把学生对象拼接成指定字符串
            StringBuilder sb = new StringBuilder();
            sb.append(stu.getName()).append("-").append(stu.getChenise()).append("-").append(stu.getMath()).append(
                    "-").append(stu.getEnghish()).append("-").append(stu.getSun());
            //写数据
            bw.write(sb.toString());
            bw.newLine();
            bw.flush();
        }

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

    }
}

  1. 案例2:复制单级目录
package com.jxufe_ldl.selfstudy;

import java.io.*;

/*
    复制单级文件夹中的内容
 */
public class OneFolderCopy {
    public static void main(String[] args) throws IOException {
        // 创建源数据文件对象
        File srcFolder = new File("D://jxufe");

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

        // 创建目的数据文件对象
        File destFolder = new File("day10//java", srcFolderName);

        // 创建目的数据的目录
        if (!destFolder.exists()) {
            destFolder.mkdir();
        }

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

        // 遍历文件数组
        for (File srcFile : listFiles) {
            // 获取文件名
            String foldername = srcFile.getName();
            //拼接目的文件对象
            File destFile = new File(destFolder, foldername);

            // 复制文件
            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 = 0;
        while ((len = bis.read(bys)) != -1) {
            bos.write(bys, 0, len);
        }

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

  1. 案例3:复制多级目录
package com.jxufe_ldl.selfstudy;

import java.io.*;

public class listFolderCopy {
    public static void main(String[] args) throws IOException{
        // 创建源数据文件对象
        File srcFile = new File("D:\\jxufe");

        // 创建目的地数据文件对象
        File distFile = new File("F:\\");

        // 把D盘的文件赋值到F盘
        copyFolder(srcFile, distFile);

    }

    private static void copyFolder(File srcFile, File distFile) throws IOException {
        // 判断srcFile是否为目录
        if (srcFile.isDirectory()) {
            // 在目的地下创建和源数据一样的目录
            File newFolder = new File(distFile, srcFile.getName());
            if (!newFolder.exists()) {
                newFolder.mkdir();
            }

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

            // 变量files数组,得到每一个File对象
            for (File file:files) {
                copyFolder(file, newFolder);
            }
        } else {
            // 否则就是文件,就把该文件用字节流复制到指定目录下
            File newFile = new File(distFile, 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 = 0;
        while ((len = bis.read(bys)) != -1) {
            bos.write(bys, 0, len);
        }

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

标准输入流和输出流

  • System.in:标准输入流,是一个字节输入流,可以接收控制台输入的内容
    BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

    String s = br.readLine();

  • System.out:标准输出流,是一个字节输出流,可以将内容输出到控制台。

打印流:打印流都是输出流

  • 字节打印流:PrintStream
    1. write(97)、print(97)以及println(97)的区别?
      write(97); //a
      print(97); //97
      println(97); //97并且换行
  • 字符打印流:PrintWriter
    1. 构造方法:
      PrintWriter​(String fileName):根据字符串类型的文件路径创建字符打印流对象,需要手动调用flush方法获取close方法刷新到文件中。
      PrintWriter​(Writer out, boolean autoFlush):创建字符打印流对象,需要一个Writer,参数2表示自动刷新。当调用println ,printf ,或format方法时自动刷新。
    2. 成员方法:
      public void println("字符串");
package com.jxufe_ldl.class02;

import java.io.*;

public class PrintWriteDemo {
    public static void main(String[] args) {
        // 复制文件
        // 1. 创建字符缓冲输入流和字符打印流对象
        try(BufferedReader br = new BufferedReader(new FileReader("day10//oneFloderCopy.java"));
            PrintWriter pw = new PrintWriter(new FileWriter("day10//java//oneFloderCopy.java"));) {
            // 复制文件
            String line;
            while ((line = br.readLine()) != null) {
                pw.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

序列化流和反序列化流

  • 序列化:将对象写到文件中叫做序列化

  • 反序列化:将文件中的对象读出来叫做反序列化

    1. 序列化流:ObjectOutputStream 是一个字节流,能够将一个对象写到文件中
    2. 构造方法:
      ObjectOutputStream​(OutputStream out):创建一个写入指定的OutputStream的ObjectOutputStream。
    3. 成员方法:
      void writeObject​(Object obj):将obj对象写到文件中
    4. 反序列化流:ObjectInputStream 是一个字节流,能够将文件中的对象读到内存中
    5. 构造方法:
      ObjectInputStream​(InputStream in):创建从指定的InputStream读取的ObjectInputStream。
    6. 成员方法:
      Object readObject​():从ObjectInputStream读取一个对象。
  • 注意事项:
    1. 序列化的对象必须实现一个Serializable标记型接口。
    2. class文件中的序列化id和序列化文件中的id不一致导致InvalidClassException异常

    解决办法:固定序列化id值:private static final long serialVersionUID = 42L;

  1. 如果某个成员变量不想被序列化,那么使用transient修饰该成员变量

  2. 如果序列化了多个对象需要使用使用反序列化流while循环读对象,读到文件的末尾不是返回null,而是抛出一个EOFException异常

    解决办法:
    方式1:使用try…catch处理异常,不打印异常信息。
    方式2:如果是需要将多个对象序列化到文件中,可以先将对象存到集合中,将集合序列化到文件中。(还是序列化一个对象)

package com.jxufe_ldl.class02;

import java.io.Serializable;

public class Student implements Serializable {
    private static final long serialVersionUID = 42L;
    private String name;
    private int chinese;
    private transient int math;


    public Student() {
    }

    public Student(String name, int chinese, int math) {
        this.name = name;
        this.chinese = chinese;
        this.math = math;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getChinese() {
        return chinese;
    }

    public void setChinese(int chinese) {
        this.chinese = chinese;
    }

    public int getMath() {
        return math;
    }

    public void setMath(int math) {
        this.math = math;
    }

    public int getSum() {
        return chinese + math;
    }

    @Override
    public String toString() {
        return name + "," + chinese + "," + math + "," + getSum();
    }
}

package com.jxufe_ldl.class02;

import java.io.*;

public class SerializableObjectDemo {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        write();

        read();
    }

    private static void read() throws IOException, ClassNotFoundException {
        // 创建反序列化对象
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("day10//java//oos.txt"));

        // 反序列化对象
        Student s1 = (Student) ois.readObject();

        // 打印
        System.out.println(s1);

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

    private static void write() throws IOException {
        // 创建序列化对象
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("day10//java//oos.txt"));
        // 创建一个学生对象
        Student s1 = new Student("于曼丽", 99, 98);

        // 序列化对象
        oos.writeObject(s1) ;

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

Properties集合

  • 构造方法:
    Properties prop=new Properties()
  • 成员方法:
    Object setProperty​(String key, String value):根据key存value值,返回值是被替换的value。
    String getProperty​(String key):根据key获取对应的value值
  • Properties集合和IO流结合使用
    1. 将集合中的数据存到文件中:
      void store​(Writer writer, String comments):参数2comments表示添加的数据的描述信息,相当于注释。可以是null表示没有
    2. 将文件中的数据读到集合中
      void load​(Reader reader):读取文件中的数据到集合中。
package com.jxufe_ldl.class03;

import java.util.Random;
import java.util.Scanner;

public class Guess {
    public Guess() {
    }

    public void start() {
        // 产生一个随机数
        Random r = new Random();
        int num = r.nextInt(100)+1;

        // 键盘录入一个数字
        Scanner sc = new Scanner(System.in);

        while (true) {
            System.out.println("请输入你猜的数字");
            int guessNum = sc.nextInt();

            if (guessNum > num) {
                System.out.println("你猜大了");
            } else if (guessNum < num) {
                System.out.println("你猜小了");
            } else {
                System.out.println("恭喜你,猜对了!");
                break;
            }
        }
    }
}

package com.jxufe_ldl.class03;

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

/*
    实现玩猜数字小游戏,试玩3次,3次之后显示请充值
    分析:
        1. 创建玩游戏的方法
        2. 编写一个配置文件
        3. 使用Properties中的load方法加载配置文件
        4. 玩游戏

 */
public class GuessDemo {
    public static void main(String[] args) throws IOException {
        // 创建Guess对象
        Guess g = new Guess();
        // 创建Properties对象
        Properties prop = new Properties();

        // 常见字符输入流对象
        FileReader fr = new FileReader("day10//java//guess.properties");

        // 调用load方法加载到集合中
        prop.load(fr);
        fr.close();
        int count = Integer.parseInt(prop.getProperty("count"));
        if (count <= 3) {
            g.start();
            count++;
            // 更新配置文件
            prop.setProperty("count", String.valueOf(count));
            FileWriter fw = new FileWriter("day10//java//guess.properties");
            prop.store(fw, null);
            fw.close();
        } else {
            System.out.println("请充值!");
        }
    }

}

guess.properties // 记录游戏次数的配置文件

#Thu Aug 15 19:44:08 CST 2019
count=1
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值