• Java SE 学习笔记(十四)—— IO流(3)


    1 缓冲流

    1.1 缓冲流概述


    我们之前学习的字节流、字符流属于基础流、原始流,性能其实不是最好的,缓冲流读写数据的性能更好

    在这里插入图片描述

    缓冲流也称为高效流、高级流,其自带缓冲区,可以提高原始字节流、字符流读写数据的性能。功能上并无很大变化,性能提升了。

    1.2 字节缓冲流


    字节缓冲输入流:

    • BufferedInputStream ,提高字节输入流读取数据的性能。
    • 字节缓冲输入流自带了 8KB 缓冲池,以后我们直接从缓冲池读取数据,所以性能较好。

    字节缓冲输出流:

    • BufferedOutputStream ,提高字节输出流读取数据的性能。
    • 字节缓冲输出流自带了 8KB 缓冲池,数据就直接写入到缓冲池中去,写数据性能极高了。

    构造方法

    在这里插入图片描述

    为什么构造方法需要的是字节流,而不是具体的文件或者路径呢?

    • 字节缓冲流仅仅提供缓冲区,而真正读写数据还是得依靠基本的字节流对象进行操作

    1.3 字符缓冲流


    符缓冲输入流:

    • BufferedReader,提高字符输入流读取数据的性能,除此之外多了按照行读取数据的功能。

    在这里插入图片描述
    在这里插入图片描述

    字符缓冲输出流:

    • BufferedWriter ,提高字符输出流写取数据的性能,除此之外多了换行功能

    在这里插入图片描述

    在这里插入图片描述

    示例代码:

    import java.io.*;
    
    public class Test1 {
        public static void main(String[] args) throws IOException {
            FileWriter f1 = new FileWriter("D:\\StudyTools\\test.txt");
            BufferedWriter bw = new BufferedWriter(f1);
    
            bw.write("我");
            bw.write("abc");
            bw.newLine();
            bw.write("hhhh");
            bw.close(); // 字符首先写到缓冲池,关闭文件后刷新,写入的文件有内容显示
    
            FileReader f2 = new FileReader("D:\\StudyTools\\test.txt");
            BufferedReader br = new BufferedReader(f2);
            System.out.println(br.readLine()); // 我abc
            System.out.println(br.readLine()); // hhhh
            System.out.println(br.readLine()); // null
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    推荐使用哪种方式提高字节流读写数据的性能?

    • 建议使用字节缓冲输入流、字节缓冲输出流,结合字节数组的方式, 目前来看是性能最优的组合。

    2 转换流


    使用字符流读取中文不会乱码,那如果读取的文件编码与代码编码不一致怎么办呢?

    在这里插入图片描述

    2.1 字符输入转换流


    针对文件编码与代码编码不一致导致的乱码问题,如何解决?

    • 使用字符输入转换流
      • 可以提取文件的原始字节流(原始字节不会存在问题)
      • 然后把字节流以指定编码转换成字符输入流(这样字符输入流的字符就不会乱码了)

    字符输入转换流: InputStreamReader ,可以把原始的字节流按照指定编码转换成字符输入流。

    在这里插入图片描述

    示例代码:

    import java.io.BufferedReader;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    
    /*
    * 代码是UTF-8,文件是GBK
    * */
    public class Test1 {
        public static void main(String[] args) throws IOException {
            // 1. 提取字节码文件的原始字节流
            FileInputStream f = new FileInputStream("D:\\StudyTools\\test.txt");
            // 2. 把原始字节流转换为字符输入流
    //        InputStreamReader isr = new InputStreamReader(f); // 默认UTF-8转换字符流还是会乱码
            InputStreamReader isr = new InputStreamReader(f,"GBK");
            BufferedReader br = new BufferedReader(isr);
            String s;
            while((s=br.readLine())!=null){
                System.out.println(s);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    2.1 字符输出转换流


    如果需要控制写出去的字符使用的编码,怎么办?

    • 可以把字符以指定编码获取字节后再使用字节输出流写出去
      • "我爱你中国" .getBytes(编码)
    • 也可以使用字符输出转换流实现

    字符输出转换流: OutputStreamWriter ,可以指定编码把字节输出流转换成字符输出流,从而可以指定写出去的字符编码

    在这里插入图片描述

    示例代码:

    import java.io.*;
    
    /*  代码是UTF-8
        指定写出去文件的字符编码GBK
    * */
    
    public class Test {
        public static void main(String[] args) throws IOException {
            // 1. 定义一个字节输出流
            FileOutputStream os = new FileOutputStream("io/src/out.txt");
            // 2. 把原始的字节输出流转换成字符输出流
            OutputStreamWriter osw = new OutputStreamWriter(os,"GBK");
            BufferedWriter bw = new BufferedWriter(osw);
            bw.write("123我爱你中国");
            bw.write("123我爱你中国");
            bw.newLine();
            bw.write("123我爱你中国");
            bw.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    3 序列化


    如何把Java对象进行长久的保存?

    在这里插入图片描述

    3.1 对象序列化


    对象序列化:

    • 以内存为基准,把内存中的对象存储到磁盘文件中去。
    • 使用到的流是对象字节输出流ObjectOutputStream

    构造方法

    在这里插入图片描述

    序列化方法

    在这里插入图片描述

    示例代码

    学生对象

    import java.io.Serializable;
    
    public class Student implements Serializable {
    	// 声明序列化的版本号
        private static final long serialVerionUID=1;
        private int age;
        private String name;
        private String passwd;
        // private transient String passwd; // 表示修饰的成员变量不参与序列化
    
        public Student() {
        }
    
        public Student(int age, String name, String passwd) {
            this.age = age;
            this.name = name;
            this.passwd = passwd;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getPasswd() {
            return passwd;
        }
    
        public void setPasswd(String passwd) {
            this.passwd = passwd;
        }
    
        @Override
        public String toString() {
            return "Student{" +
                    "age=" + age +
                    ", name='" + name + '\'' +
                    ", passwd='" + passwd + '\'' +
                    '}';
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    序列化

    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.ObjectOutputStream;
    
    public class Test {
        public static void main(String[] args) throws IOException {
            // 1. 创建学生对象
            Student s = new Student(18, "小明", "123123");
            // 2. 对象序列化
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("io/src/obj.txt"));
            // 3. 调用序列化方法
            oos.writeObject(s);
            oos.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    注意:

    • 对象如果要序列化,必须实现 Serializable接口
      • 一个标记性接口,里面没有任何的抽象方法(实现一个接口就要实现里面所有的抽象方法)只要一个类实现了这个Serializable接口,那么就表示这个类的对象可以被序列化。
      • 实现该接口,不需要重写任何方法
    • transien修饰的成员变量不参与序列化
    • 序列化与反序列化的版本号必须一致

    3.2 对象反序列化


    对象反序列化:

    • 以内存为基准,把存储到磁盘文件中去的对象数据恢复成内存中的对象
    • 使用到的流是对象字节输入流ObjectInputStream

    构造方法

    在这里插入图片描述

    反序列方法

    在这里插入图片描述

    示例代码

    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    
    public class Test {
        public static void main(String[] args) throws IOException, ClassNotFoundException {
            // 1. 对象反序列化
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("io/src/obj.txt"));
            // 2. 调用反序列化方法
            Student s = (Student)ois.readObject();
            System.out.println(s);
            ois.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    4 打印流


    开发中有一种使用极为方便,性能高效的写数据的流,使用的很多。

    打印流可以实现方便高效的打印数据到文件中去。打印流一般是指: PrintStreamPrintWriter 两个类。

    可以实现打印什么数据就是什么数据,例如打印整数 97 写出去就是 97 ,打印 boolean 的 true ,写出去就是 true 。

    构造方法

    在这里插入图片描述

    在这里插入图片描述

    打印方法(二者一样)

    在这里插入图片描述

    示例代码

    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.PrintStream;
    
    public class printDemo {
        public static void main(String[] args) throws FileNotFoundException {
            // 创建一个打印流对象
    //        PrintStream ps = new PrintStream("io/src/ps.txt");
    //        PrintStream ps = new PrintStream(new File("io/src/ps.txt"));
            PrintStream ps = new PrintStream(new FileOutputStream("io/src/ps.txt"));// 如果要追加数据,在低级管道后面加true
    
            ps.println(true);
            ps.println("我爱你中国");
            ps.println(123);
            ps.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    PrintStreamPrintWriter 的区别

    • 打印数据功能上是一模一样的,都是使用方便,性能高效(核心优势)
    • PrintStream 继承自字节输出流 OutputStream ,支持写字节数据的方法。
    • PrintWriter 继承自字符输出流 Writer ,支持写字符数据出去。

    输出语句重定向:属于打印流的一种应用,可以把输出语句的打印位置改到文件

    import java.io.FileNotFoundException;
    import java.io.PrintStream;
    
    public class printDemo {
        public static void main(String[] args) throws FileNotFoundException {
            // 控制台打印
            System.out.println("床前明月光,");
            System.out.println("疑是地上霜。");
            // 改变输出语句的位置(将以下两句输出到文件)
            PrintStream ps = new PrintStream("io/src/print.txt");
            System.setOut(ps);
            System.out.println("举头望明月,");
            System.out.println("低头思故乡。");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    5 与Properties结合使用


    Properties 集合是一个Map体系的集合类,但是一般我们不会当集合使用,因为HashMap更好用,其可以保存到流中或从流中加载。

    Properties核心作用Properties 代表的是一个属性文件,可以把自己对象中的键值对信息存入到一个属性文件中去。

    • 属性文件:后缀是 .properties 结尾的文件 , 里面的内容都是 key=value ,后续做系统配置信息的。(那么这就涉及到文件内容的读写了,结合IO流)

    Properties 和 IO 流结合的方法:

    在这里插入图片描述

    示例代码:

    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.util.Properties;
    
    public class PropertiesDemo {
        public static void main(String[] args) throws IOException {
            // 1. 使用Properties将键值对信息保存到属性文件中去(写)
    //        Properties p = new Properties();
    //        p.setProperty("admin","123456");
    //        p.setProperty("huwei","000000");
    //        p.setProperty("anni","888888");
    //        p.store(new FileWriter("io/src/users.properties"),"这是备注信息");
    
            // 2. Properties读取属性文件中的属性信息(读)
            Properties properties = new Properties();
            System.out.println(properties);
            // 加载属性文件中的键值对数据到属性对象properties中去
            properties.load(new FileReader("io/src/users.properties"));
            System.out.println(properties);
     		// 获取属性值
            String rs1 = properties.getProperty("admin");
            System.out.println(rs1); // 123456
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    6 IO 框架


    commons-io 是 apache 开源基金组织提供的一组有关 IO 操作的类库,可以提高 IO 功能开发的效率。commons-io 工具包提供了很多有关 io 操作的类。有两个主要的类 FileUtilsIOUtils

    FileUtils 主要有如下方法:

    在这里插入图片描述

    导入 commons-io-2.15.0.jar ,用其简化 IO 流读写

    • 在项目中创建一个文件夹 lib
    • commons-io-2.15.0.jar文件复制到 lib 文件夹
    • 在 jar 文件上点击右键,选择Add as Library,点击OK
    • 在类中导包使用

    示例代码

    import org.apache.commons.io.FileUtils;
    import org.apache.commons.io.IOUtils;
    
    import java.io.*;
    
    public class CommonsDemo {
        public static void main(String[] args) throws IOException {
            // 文件的复制
            IOUtils.copy(new FileInputStream("io/src/ps.txt"), new FileOutputStream("io/src/ps_copy.txt"));
            // 文件复制到某个文件夹下
            FileUtils.copyFileToDirectory(new File("io/src/ps.txt"),new File("D:\\"));
            // 文件夹复制到某个文件夹下
            FileUtils.copyDirectoryToDirectory(new File("io/src"),new File("D:\\"));
            // 删除文件夹(有内容)
            FileUtils.deleteDirectory(new File("D:\\src"));
            // 删除文件
            FileUtils.delete(new File("D:\\ps.txt"));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
  • 相关阅读:
    pyModbusTCP 读取零点 CN- 8031 /CT-121F DI 数字输入
    Tomcat 漏洞处理
    IDEA热部署
    学妹学Java(一)
    代理IP供应商的代理池大小怎么看?
    STM32F303RE 四个ADC同步规则采样
    Matlab杂项记录
    【原创】java+swing+mysql爱心捐赠管理系统设计与实现
    JS中oninput和onchange事件的区别
    kotlin基础之高阶函数
  • 原文地址:https://blog.csdn.net/hu_wei123/article/details/134065506