Java进阶——IO流(II)

本文涉及的产品
RDS MySQL DuckDB 分析主实例,基础系列 4核8GB
RDS AI 助手,专业版
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
简介: 序列化和反序列化1. 序列化就是在保存数据时,保存数据的值和数据类型2. 反序列化就是在恢复数据时,恢复数据的值和数据类型3. 需要让某个对象支持序列化,必须让其类是可序列化的,必须实现如下两个接口之一:Serializable(标记接口)和Externalizable

三、节点流和处理流

基本介绍:

image-20221114151045919

  • 节点流和处理流

image-20221114151238588

3.1、处理流BufferedReader和BufferedWriter

  • BufferedReader和BufferedWriter属于字符流,是按照字符来读取数据的关闭时,只需要关闭外层

BufferedReader代码演示:

import org.junit.jupiter.api.Test;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;

/**
 * @author java小豪
 * @version 1.0.0
 * @date 2022/11/16
 * @description 处理流
 */
public class BufferedReader_ {
    public static void main(String[] args) {

    }

    @Test
    public void read() throws Exception {
        String filePath = "F:\\file\\story.txt";
        // 创建BufferedReader对象
        BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
        // 读取
        String line;
        // 说明
        // 1.bufferedReader.readLine() 是按行读取文件
        // 2.当返回null 时,表示文件读取完毕
        while ((line = bufferedReader.readLine()) != null) {
            System.out.print(line);
        }

        // 关闭流 只需要关闭 BufferedReader, 因为底层会自动关闭 节点流
        bufferedReader.close();
    }
}

BufferedWriter代码演示:不能处理二进制文件[pdf/word/声音/图片等]

import org.junit.jupiter.api.Test;

import java.io.*;

/**
 * @author java小豪
 * @version 1.0.0
 * @date 2022/11/16
 * @description 文件拷贝
 */
public class BufferedCopy_ {
    public static void main(String[] args) {

    }

    @Test
    public void test() {
        String filePath = "F:\\file\\ok.txt";
        String destFilePath = "F:\\file\\ok1.txt";
        BufferedReader bufferedReader = null;
        BufferedWriter bufferedWriter = null;
        String line;
        try {
            bufferedReader = new BufferedReader(new FileReader(filePath));
            bufferedWriter = new BufferedWriter(new FileWriter(destFilePath));
            // readLine() 读取一行内容,但是没有换行
            while ((line = bufferedReader.readLine()) != null) {
                // 每读取一行就写进去
                bufferedWriter.write(line);
                // 插入一个换行
                bufferedWriter.newLine();
            }
            System.out.println("拷贝完毕....");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (bufferedReader != null) {
                    // 关闭流
                    bufferedReader.close();
                }
                if (bufferedWriter != null) {
                    // 关闭流
                    bufferedWriter.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}

3.2、处理流BufferedInputStream和BufferedOutputStream

  • 使用BufferedInputStream和BufferedOutputStream可以完成二进制文件的拷贝
import org.junit.jupiter.api.Test;

import java.io.*;

/**
 * @author java小豪
 * @version 1.0.0
 * @date 2022/11/16
 * @description 文件拷贝
 */
public class BufferedCopy1 {
    public static void main(String[] args) {

    }

    @Test
    public void copy() {
        String srcPath = "F:\\file\\1.jpg";
        String destPath = "F:\\file\\2.jpg";
        // 创建BufferedInputStream和BufferedOutputStream
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            bis = new BufferedInputStream(new FileInputStream(srcPath));
            bos = new BufferedOutputStream(new FileOutputStream(destPath));

            // 循环读取文件,并写入到 destPath
            byte[] bytes = new byte[1024];
            int readLine = 0;
            // 当返回 -1 时表示读取完毕
            while((readLine = bis.read(bytes)) != -1) {
                bos.write(bytes, 0, readLine);
            }
            System.out.println("文件拷贝完毕....");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭流,关闭外层的处理流
            try {
                if (bis != null) {
                    bis.close();
                }
                if (bos != null) {
                    bos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }
}

3.3、对象流ObjectInputStream和ObjectOutputStream

  • 序列化和反序列化
  1. 序列化就是在保存数据时,保存==数据的值==和==数据类型==
  2. 反序列化就是在恢复数据时,恢复==数据的值==和==数据类型==
  3. 需要让某个对象支持序列化,必须让其类是可序列化的,必须实现如下两个接口之一:Serializable(标记接口)和Externalizable

ObjectInputStream和ObjectOutputStream的类图:


image-20221116140250301

image-20221116140231862

使用ObjectOutputStream 序列化基本数据类行和一个Dog对象(name, age)并保存到data.dat文件里面

import java.io.*;

/**
 * @author java小豪
 * @version 1.0.0
 * @date 2022/11/16
 * @description ObjectOutputStream的使用
 */
public class ObjectOutputStream_ {
    public static void main(String[] args) throws IOException {
        // 序列化后保存的文件格式,不是纯文本,而是按照它的格式保存的
        String filePath = "F:\\file\\data.dat";

        ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(filePath));
        // 序列化数据
        os.write(100);
        // 自动装箱boolean ----> Boolean (实现了 Serializable)
        os.writeBoolean(true);
        // 自动装箱char ----> Character (实现了 Serializable)
        os.writeChar('a');
        os.writeUTF("java小豪");
        // 保存一个Dog对象
        os.writeObject(new Dog("旺财", 3));

        os.close();
        System.out.println("数据保存完毕(序列化形式)");

    }
}
// 如果需要序列化某个类的对象,实现Serializable
class Dog implements Serializable {
    private String name;
    private int age;

    public Dog(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
  • 注意事项

    • 读写顺序要一致
    • 要求实现序列化或反序列化对象实现Serializable
    • 序列化对象时,默认将里面的所有属性都进行序列化,除了static或transient修饰的成员
    • 序列化对象时,要求里面的属性的类型也需要实现序列化接口
    • 序列化具备可继承性,也就是某类实现了序列化,他的所有子类也已经默认实现了序列化

3.4、标准输入输出流

  • System.in和System.out
/**
 * @author java小豪
 * @version 1.0.0
 * @date 2022/11/16
 * @description 标准输入和输出流
 */
public class InputAndOutput {
    public static void main(String[] args) {
        //System类里面的一个属性 public final static InputStream in = null;
        // 编译类型 为 InputStream 运行类型 BufferedInputStream
        System.out.println(System.in.getClass());

        // System.out 是 public final static PrintStream out = null;
        // 编译类型 为 PrintStream 运行类型 为PrintStream 标准输出(显示器)
        System.out.println(System.out.getClass());
    }
}

3.5、转换流InputStreamReader和OutputStreamWriter

  1. InputStreamReader: Reader的子类,可以将InputStream(字节流)包装成(转换)Reader(字符流)
  2. OutputStreamWriter: Writer的子类,可以实现将OutputStream(字节流)包装成Writer(字符流)
  3. 当处理纯文本数据时,如果使用字符流效率更高,并且可以有效解决中文问题,所以建议将字节流转换成字符流
  4. 可以在使用时指定编码格式(比如 utf-8, gbk, gb2312, ISO8855-1等)

InputStreamReader的类图:

image-20221128215734373


OutputStream的类图:

image-20221128220657123


示例1:字节流FileInputStream包装成(转换成)字符流InputStreamReader,对文件进行读取(按照UTF-8/GBK格式)进而包装成BufferedReader

import java.io.*;

/**
 * @author java小豪
 * @version 1.0.0
 * @date 2022/11/28
 * @description 使用InputStreamReader解决中文乱码问题
 * <p>
 *     将字节流 FileInputStream 转换成 InputStreamReader, 指定编码gbk/utf-8
 * </p>
 */
public class InputStreamReader_ {
    public static void main(String[] args) throws IOException {

        String filePath = "F:\\file\\a.txt";
        // 1. new FileInputStream 转成 InputStreamReader 指定编码为GBK
        InputStreamReader isr = new InputStreamReader(new FileInputStream(filePath), "GBK");
        // 2. 把 InputStreamReader 传入 BufferedReader
        BufferedReader br = new BufferedReader(isr);

        // 将 2 和 3 和在一起
        // BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), "GBK"));
        // 3. 读取
        String s = br.readLine();
        System.out.println("读取文件的内容为:" + s);
        // 4. 关闭外层流
        br.close();
    }
}

示例2:将字节流FileOutputStream包装成(转换成)字符流OutputStreamWriter,对文件进行写入(按照GBK格式,可以指定其他:UTF-8)

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;

/**
 * @author java小豪
 * @version 1.0.0
 * @date 2022/11/28
 * @description 使用OutputStreamWriter将FileOutputStream字节流,转换成字符流 OutputStreamWriter
 */
public class OutputStreamWriter_ {
    public static void main(String[] args) throws IOException {

        String filePath = "F:\\file\\a.txt";
        String charSet = "UTF-8";
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(filePath), charSet);
        osw.write("hi, 孙悟空");
        osw.close();
        System.out.println("按照 " + charSet + "保存文件成功~");
    }
}

3.6、打印流PrintStream 和 PrintWriter

注意:打印流只有输出流,没有输入流
PrintStream的类图

image-20221128223541729

PrintWriter的类图

image-20221128223641038

PrintStream示例:

import java.io.IOException;
import java.io.PrintStream;

/**
 * @author java小豪
 * @version 1.0.0
 * @date 2022/11/28
 * @description 演示PrintStream(字节打印流)、
 */
public class PrintStream_ {
    public static void main(String[] args) throws IOException {
        PrintStream ps = System.out;
        // 默认情况下,PrintStream 输出数据的位置是标准输出
        /*
        public void print(String s) {
            if (s == null) {
                s = "null";
            }
            write(s);
         }
         */
        ps.println("john Hello");
        // 因为print底层使用write,所以我们可以调用write进行打印/输出
        ps.write("孙悟空,你好".getBytes());
        ps.close();

        //我们可以修改打印输出流的位置,修改成到 "F:\\file\\f1.txt"
        System.setOut(new PrintStream("F:\\file\\f1.txt"));
        System.out.println("hello, 孙悟空");
    }
}

PrintWriter示例:

import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * @author java小豪
 * @version 1.0.0
 * @date 2022/11/28
 * @description 演示PrintWriter的使用
 */
public class PrintWriter_ {
    public static void main(String[] args) throws IOException {

//        PrintWriter pw = new PrintWriter(System.out);
        PrintWriter pw = new PrintWriter(new FileWriter("F:\\file\\f2.txt"));
        pw.print("hello, 北京~");
        pw.close();
    }
}

四、Properties类

properties类可以轻松的处理*.properties文件

Properties类常见方法:

  • load:加载配置文件的键值对到Properties对象
  • list:将数据显示到指定位置
  • getProperty(key):根据键获取值
  • setProperty(key, value):设置键值对到Properties对象
  • store:将Properties中的键值对存储到配置文件,在idea中保存文件如果有中文,会存储为Unicode码

示例1:读取mysql.properties文件,并得到ip,user 和 pwd

  • 传统方法
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

/**
 * @author java小豪
 * @version 1.0.0
 * @date 2022/11/28
 * @description 演示Properties类的使用
 */
public class Properties01 {
    public static void main(String[] args) throws IOException {

        // 读取mysql.properties文件并得到ip、user和pwd
        BufferedReader br = new BufferedReader(new FileReader("src\\mysql.properties"));
        String line = "";
        while((line = br.readLine()) != null ) {
            String[] split = line.split("=");
            System.out.println(split[0] + "值是:" + split[1]);
        }
        br.close();
    }
}
  • 使用Properties类进行读取
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;

/**
 * @author java小豪
 * @version 1.0.0
 * @date 2022/11/28
 * @description
 */
public class Properties02 {
    public static void main(String[] args) throws IOException {
        // 使用Properties 类来读取mysql.properties 文件

        // 1.创建Properties 对象
        Properties properties = new Properties();
        // 2.加载指定的配置文件
        properties.load(new FileReader("src/mysql.properties"));
        // 3.把k-v显示到控制台
        properties.list(System.out);
        // 4.根据键获取对应的值
        String user = properties.getProperty("username");
        String pwd = properties.getProperty("password");
        System.out.println("用户名=" + user);
        System.out.println("密码=" + pwd);
    }
}
  • 使用Properties修改配置文件
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;

/**
 * @author java小豪
 * @version 1.0.0
 * @date 2022/11/29
 * @description
 */
public class Properties03 {
    public static void main(String[] args) throws IOException {
        // 使用Properties 类来创建 配置文件,修改配置文件内容
        Properties properties = new Properties();
        // 创建
        // 1.如果该文件没有key,就是创建
        // 2.如果该文件有key,就是修改
        properties.setProperty("charset", "utf-8");
        properties.setProperty("user", "孙悟空");
        properties.setProperty("pwd", "888888");

        // 将k-v 存储在文件中
        properties.store(new FileOutputStream("src\\mysql2.properties"), null);
        System.out.println("保存文件成功");
        
    }
}
相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
目录
相关文章
|
4月前
|
Java Unix Go
【Java】(8)Stream流、文件File相关操作,IO的含义与运用
Java 为 I/O 提供了强大的而灵活的支持,使其更广泛地应用到文件传输和网络编程中。!但本节讲述最基本的和流与 I/O 相关的功能。我们将通过一个个例子来学习这些功能。
237 1
|
6月前
|
Java 测试技术 API
Java IO流(二):文件操作与NIO入门
本文详解Java NIO与传统IO的区别与优势,涵盖Path、Files类、Channel、Buffer、Selector等核心概念,深入讲解文件操作、目录遍历、NIO实战及性能优化技巧,适合处理大文件与高并发场景,助力高效IO编程与面试准备。
|
6月前
|
SQL Java 数据库连接
Java IO流(一):字节流与字符流基础
本文全面解析Java IO流,涵盖字节流、字符流及其使用场景,帮助开发者理解IO流分类与用途,掌握文件读写、编码转换、异常处理等核心技术,通过实战案例提升IO编程能力。
|
7月前
|
存储 Java Linux
操作系统层面视角下 Java IO 的演进路径及核心技术变革解析
本文从操作系统层面深入解析Java IO的演进历程,涵盖BIO、NIO、多路复用器及Netty等核心技术。分析各阶段IO模型的原理、优缺点及系统调用机制,探讨Java如何通过底层优化提升并发性能与数据处理效率,全面呈现IO技术的变革路径与发展趋势。
169 2
|
7月前
|
监控 Java API
现代 Java IO 高性能实践从原理到落地的高效实现路径与实战指南
本文深入解析现代Java高性能IO实践,涵盖异步非阻塞IO、操作系统优化、大文件处理、响应式网络编程与数据库访问,结合Netty、Reactor等技术落地高并发应用,助力构建高效可扩展的IO系统。
232 0
|
11月前
|
存储 网络协议 安全
Java网络编程,多线程,IO流综合小项目一一ChatBoxes
**项目介绍**:本项目实现了一个基于TCP协议的C/S架构控制台聊天室,支持局域网内多客户端同时聊天。用户需注册并登录,用户名唯一,密码格式为字母开头加纯数字。登录后可实时聊天,服务端负责验证用户信息并转发消息。 **项目亮点**: - **C/S架构**:客户端与服务端通过TCP连接通信。 - **多线程**:采用多线程处理多个客户端的并发请求,确保实时交互。 - **IO流**:使用BufferedReader和BufferedWriter进行数据传输,确保高效稳定的通信。 - **线程安全**:通过同步代码块和锁机制保证共享数据的安全性。
513 23
|
缓存 网络协议 Java
JAVA网络IO之NIO/BIO
本文介绍了Java网络编程的基础与历史演进,重点阐述了IO和Socket的概念。Java的IO分为设备和接口两部分,通过流、字节、字符等方式实现与外部的交互。
430 0
|
Java
java 中 IO 流
Java中的IO流是用于处理输入输出操作的机制,主要包括字节流和字符流两大类。字节流以8位字节为单位处理数据,如FileInputStream和FileOutputStream;字符流以16位Unicode字符为单位,如FileReader和FileWriter。这些流提供了读写文件、网络传输等基本功能。
262 10
|
存储 缓存 Java
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)
这篇文章详细介绍了Java中的IO流,包括字符与字节的概念、编码格式、File类的使用、IO流的分类和原理,以及通过代码示例展示了各种流的应用,如节点流、处理流、缓存流、转换流、对象流和随机访问文件流。同时,还探讨了IDEA中设置项目编码格式的方法,以及如何处理序列化和反序列化问题。
447 1
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)