Java IO

本文详细介绍了Java中的IO流,包括递归遍历目录、字节流和字符流的区别与操作,如字节流的写入和读取方式,字符流的写入和读取,以及集合和文件的操作。还涵盖了对象的序列化和反序列化,以及Properties类的使用。内容深入浅出,适合Java初学者和进阶者学习。
摘要由CSDN通过智能技术生成

0. 概述

按照操作方式分类

在这里插入图片描述

按照操作对象分类

在这里插入图片描述

1.递归遍历目录

public class Demo02 {
    public static void main(String[] args) {
        File f = new File("E:\\MISC");
        getAllFile(f);
    }

    public static void getAllFile(File f) {
        //获取目录下所有文件或目录,并赋值给File数组
        File[] files = f.listFiles();
        //循环遍历,获取每一个file对象
        //Objects.requireNonNull(files)判断非空
        for (File file : Objects.requireNonNull(files)) {
            //如果是文件,则递归调用方法
            if (file.isDirectory()) {
                getAllFile(file);
                //否则输出绝对路径
            } else System.out.println(file.getAbsolutePath());
        }
    }
}

2. 字节流

2.1 字节流和字符流区别

  • 用txt打开,人能看懂的是字符流,看不懂的是字节流
  • 用Input和Output的是字节流,用Wridter和Reader的是字符流,带Buffer的是缓冲流
  • 获取文本信息的二进制文件,比如图片,mp3,视频文件等,使用字节流
  • 文本信息使用字符流
  • 字符流=字节流+编码表

2.2 字节流写数据

字节流写数据的三种方式
第一种:一次写一个字节的数据
public class Demo03 {
    public static void main(String[] args) throws IOException {
        //此处使用的是相对路径
        FileOutputStream fos = new FileOutputStream("test.txt");
        /*
            做了三件事情:
                调用系统功能创建文件
                创建字节输出对象
                让字节输出对象指向创建好的文件
         */
        fos.write(97);
        //释放资源
        fos.close();
    }
}
第二种:一次写一个字节数组的数据
public class Demo03 {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("test.txt");
        //获取字节数组
        byte[] bytes = "啊哈哈哈".getBytes();
        //写入数据
        fos.write(bytes);
        //释放资源
        fos.close();
    }
}
第三种:一次写一个字节数组的部分数据
public class Demo03 {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("test.txt");
        byte[] bytes = "啊哈哈哈".getBytes();
        //写入[啊哈],一个中文占3个字节
        fos.write(bytes,0,6);
        //释放资源
        fos.close();
    }
}
字节流写数据实现换行
public class Demo04 {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("demo.txt");
        for (int i = 0; i < 10; i++) {
            //写入数据
            fos.write("bug".getBytes());
            //换行操作
            fos.write("\r\n".getBytes());
        }
        fos.close();
    }
}

不同操作系统的换行符不同

  • Windows:\r\n
  • Linux:\n
  • Mac:\r
字节流数据追加写入
public class Demo04 {
    public static void main(String[] args) throws IOException {
        //创建字节输出流对象
        FileOutputStream fos = new FileOutputStream("demo.txt", true);
        //循环写入数据
        for (int i = 0; i < 10; i++) {
            fos.write("bug".getBytes());
            fos.write("\r\n".getBytes());
        }
        fos.close();
    }
}

FileOutputStream fos = new FileOutputStream("demo.txt", true);中两个参数分别为(写入的文件位置,是否追加写入)。其中第二个参数若不填或为false,则视为不追加写入,每次运行写入均是覆盖原文件从头开始写入数据。

2.3 字节流读数据

读取中文数据
public class Demo06 {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("test.txt");

        // 声明一个字节数组
        byte[] b = new byte[1024];
        StringBuffer str = new StringBuffer();
        int len;
        // 循环读取
        while ((len = fis.read(b)) != -1) {
            str.append(new String(b, 0, len));
        }
        System.out.println(str.toString());
        fis.close();
    }
}
复制文本文件
public class Demo07 {
    public static void main(String[] args) throws IOException {
        //根据数据源创建字节输入流对象
        FileInputStream fis = new FileInputStream("test.txt");
        //根据目标位置创建字节输出流对象
        FileOutputStream fos = new FileOutputStream("E:\\demo\\test.txt");
        //通过循环读写数据达到复制文本文件的目的
        int by;
        while ((by = fis.read()) != -1) {
            fos.write(by);
        }

        fos.close();
        fis.close();
    }
}
复制图片
public class Demo08 {
    public static void main(String[] args) throws IOException {
        //根据数据源创建字节输入流对象
        FileInputStream fis = new FileInputStream("huahua.jpg");
        //根据目标位置创建字节输出流对象
        FileOutputStream fos = new FileOutputStream("E:\\demo\\huahua.jpg");
        //创建字节数组
        byte[] bytes = new byte[1024];
        //定义长度
        int len;
        //通过循环读写数据达到复制图片的目的
        while ((len = fis.read(bytes)) != -1) {
            fos.write(bytes, 0, len);
        }
        fos.close();
        fis.close();
    }
}
复制视频
public class CopyVideo {
    public static void main(String[] args) throws IOException {
        //记录开始时间
        long startTime = System.currentTimeMillis();
        //根据数据源创建输入流
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("huahua.mp4"));
        //根据目标位置创建输出流
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("E:\\demo\\huahua.mp4"));
        //定义字节数组
        byte[] bytes = new byte[1024];
        //定义长度
        int len;
        //循环读取
        while ((len = bis.read(bytes)) != -1) {
            bos.write(bytes, 0, len);
        }
        //关闭资源
        bis.close();
        bos.close();
        //记录结束时间
        long endTime = System.currentTimeMillis();
        System.out.println((endTime - startTime) + "毫秒");
    }
}

3.字符流

3.2 字符流写数据

public class OutputStreamOne {
    public static void main(String[] args) throws IOException {
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("a.txt"));

        //osw.write("啊哈");
        osw.write("abcd", 0, 3);
        //先刷新flush()后关闭
        osw.close();
    }
}

3.3 字符流读数据

public class InputStreamOne {
    public static void main(String[] args) throws IOException {
        InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"));

        char[] chs = new char[1024];
        int len;
        while ((len = isr.read()) != -1) {
            System.out.println(new String(chs, 0, len));
        }
    }
}

3.4 集合和文件操作

把集合数据写入到文件中
public class ListStreamDemo {
    public static void main(String[] args) throws IOException {
        //创建集合
        ArrayList<Student> al = new ArrayList<>();
		//创建学生对象
        Student s1 = new Student(101, "阿猫", 18, "北京");
        Student s2 = new Student(102, "阿狗", 18, "上海");
        Student s3 = new Student(103, "阿里", 18, "杭州");
        Student s4 = new Student(104, "阿豹", 18, "深圳");
        Student s5 = new Student(105, "阿毛", 18, "广州");
		//添加学生对象到集合
        al.add(s1);
        al.add(s2);
        al.add(s3);
        al.add(s4);
        al.add(s5);
		//创建字符缓冲输出流对象
        BufferedWriter bw = new BufferedWriter(new FileWriter("student.txt"));
		//遍历集合,得到学生对象
        for (Student s : al) {
            StringBuilder sb = new StringBuilder();
            sb.append(s.getNum()).append(",").append(s.getName()).append(",").append(s.getAge()).append(",").append(s.getAddress());
			//写数据
            bw.write(sb.toString());
            bw.newLine();
            bw.flush();
        }
        bw.close();
    }
}
读取文件数据到集合
public class StreamListDemo {
    public static void main(String[] args) throws IOException {
        //创建字符缓冲输入流对象
        BufferedReader br = new BufferedReader(new FileReader("student.txt"));
        //创建集合对象
        ArrayList<Student> al = new ArrayList<>();
        String line;
        //循环读数据
        while ((line = br.readLine()) != null) {
            //用string.split()方法分割字符串
            String[] split = line.split(",");
            //创建学生对象
            Student s = new Student();
            //取出字符串每个元素并进行赋值,Integer.parseInt()把String类型转换为int
            s.setNum(Integer.parseInt(split[0]));
            s.setName(split[1]);
            s.setAge(Integer.parseInt(split[2]));
            s.setAddress(split[3]);
            al.add(s);
        }
        //释放资源
        br.close();
        //遍历集合
        for (Student s : al) {
            //定义StringBuilder用于拼接
            StringBuilder sb = new StringBuilder();
            //输出拼接后的数据
            System.out.println(sb.append(s.getNum()).append(",").append(s.getName()).append(",").append(s.getAge()).append(",").append(s.getAddress()));
        }
    }
}

3.5 字符打印流

public class PrintWriterDemo {
    public static void main(String[] args) throws IOException {
        //两个参数分别为:打印输出的文件位置,是否自动刷新
        PrintWriter pw = new PrintWriter(new FileWriter("demo1.txt"), true);
        pw.println("hello");
        pw.println("world");
        pw.close();
    }
}

3.6 对象的序列化和反序列化

序列化:ObjectOutputStream
//完成序列化需要实现Serializable,Serializable只是一个标识接口没有实现方法
public class Animal implements Serializable {
    private String name;
    private int age;

    public Animal() {
    }

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
public class Output {
    public static void main(String[] args) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("oos.txt"));
        //创建阿猫对象
        Animal a = new Animal("阿猫", 3);
        //执行序列化方法
        oos.writeObject(a);
        //关闭资源
        oos.close();
    }
}
反序列化
public class Input {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("oos.txt"));
        //从ObjectInputStream读取一个对象
        Object o = ois.readObject();

        Animal a = (Animal) o;
        System.out.println(a.getName() + a.getAge());
        //释放资源
        ois.close();
    }
}
序列化流常见问题
  1. 用对象序列化流序列化一个对象后,修改对象所属的类文件会抛出InvalidClassException异常
  2. 针对上述问题的解决方法为:给对象所属的类添加一个字段serialVersionUID。注意:改字段必须是static, final, long类型,建议使用private修饰,同时建议所有可序列化的类显式声明serialVersionUid. 数组类除外,数组类具有默认的计算值不能声明一个显式的serialVersionUID,并且也放弃了匹配serialVersionUID值得要求
  3. 若一个对象中的某个成员变量的值不想被序列化,需要给成员变量添加 transient 关键字进行修饰

3.7 Properties

Properties作为Map使用
public class Demo01 {
    public static void main(String[] args) {
        //创建集合对象
        Properties p = new Properties();
        //存储元素
        p.put("a001", "阿猫");
        p.put("a002", "阿狗");
        p.put("a003", "阿豹");
        //遍历
        for (Object key : p.keySet()) {
            System.out.println(key + "," + p.get(key));
        }
        //也可以直接输出
         System.out.println(p);
    }
}
集合操作之
  • store(fw, null) 参数为(输出流,注释信息)
  • p.load(fr) 参数为(输出流)
public class Demo02 {
    public static void main(String[] args) throws IOException {
        store();
        load();
    }
    //读文件
    private static void load() throws IOException {
        Properties p = new Properties();
        FileReader fr = new FileReader("fw.txt");
        p.load(fr);
        System.out.println(p);
        fr.close();
    }
	//写文件
    private static void store() throws IOException {
        Properties p = new Properties();
        p.setProperty("b001", "阿猫");
        p.setProperty("b002", "阿狗");
        p.setProperty("b003", "阿豹");
        //调用字符流写入
        FileWriter fw = new FileWriter("fw.txt");
        p.store(fw, null);
        fw.close();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值