java IO流进阶操作

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
系统运维管理,不限时长
简介: 1.处理流(包装流)节点流是底层流/低级流,直接和数据源相连而处理流(包装流)包装节点流,即可以消除不用节点流的实现差异,也可以提供更方便的方法来完成输入输出操作可以认为,包装流是节点流的升级版本!💫包装流的两个优点:性能的提高:增加缓冲的方式来提高输入输出的效率操作的便捷:处理流可能提供了一系列便捷的方法来一次输入输出大批量的数据,使用更加灵活方便


1.处理流(包装流)


节点流是底层流/低级流,直接和数据源相连


而处理流(包装流)包装节点流,即可以消除不用节点流的实现差异,也可以提供更方便的方法来完成输入输出操作


可以认为,包装流是节点流的升级版本!💫


包装流的两个优点:


性能的提高:增加缓冲的方式来提高输入输出的效率

操作的便捷:处理流可能提供了一系列便捷的方法来一次输入输出大批量的数据,使用更加灵活方便


2.BufferedReader


BufferedReader常用于读取文本文件


使用示例:


import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
/**
 * 包装流
 * BufferedReader常用于读取文本文件
 * 包装流是节点流的升级版本
 */
public class BufferedReaderTest {
    public static void main(String[] args) throws IOException {
        String filePath = "D:\\hacker.txt";
        BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
        String line;
        // 按行读取,效率高
        while ((line = bufferedReader.readLine()) != null) {
            System.out.println(line);
        }
        // 关闭流
        bufferedReader.close();
    }
}


3.BufferedWriter


很简单,代码示例:


/**
 * BufferedWriter演示
 */
public class BufferedWriterTest {
    public static void main(String[] args) throws IOException {
        String filePath = "D:\\hacker.txt";
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath, true));
        bufferedWriter.write("大河");
        // 插入换行符
        bufferedWriter.newLine();
        bufferedWriter.write("之犬");
        bufferedWriter.close();
    }
}


4.Buffered字节处理流


程序示例:

拷贝图片


import java.io.*;
/**
 * Buffered字节处理流
 * 拷贝图片
 */
public class BufferedByteText {
    public static void main(String[] args) throws IOException {
        String srcFilePath = "D:\\xiao.jpg";
        String destFilePath = "D:\\cheng.jpg";
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            bis = new BufferedInputStream(new FileInputStream(srcFilePath));
            bos = new BufferedOutputStream(new FileOutputStream(destFilePath));
            byte[] buff = new byte[1024];
            int readLen = 0;
            // 循环读文件
            while ((readLen = bis.read(buff)) != -1) {
                // 边读边写
                bos.write(buff, 0, readLen);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            assert bis != null;
            bis.close();
            assert bos != null;
            bos.close();
        }
    }
}


5.对象处理流


Java 提供了一种对象序列化的机制,该机制中,一个对象可以被表示为一个字节序列,该字节序列包括该对象的数据、有关对象的类型的信息和存储在对象中数据的类型。


将序列化对象写入文件之后,可以从文件中读取出来,并且对它进行反序列化,也就是说,对象的类型信息、对象的数据,还有对象中的数据类型可以用来在内存中新建对象。


整个过程都是 Java 虚拟机(JVM)独立的,也就是说,在一个平台上序列化的对象可以在另一个完全不同的平台上反序列化该对象。


类 ObjectInputStream 和 ObjectOutputStream 是高层次的数据流,它们包含反序列化和序列化对象的方法。


简单来说就是,序列化和反序列化:


序列化:保存值和数据类型

反序列化:恢复保存的值和数据类型

需要让某个对象支持序列化机制,需要保证该类是可序列化的:


该类必须实现以下两个接口之一:


Serializable(优先选择)

Externalizable

序列化演示:


/**
 * ObjectOutputStream进行序列化
 */
@Test
public void Out() throws IOException {
    String filePath = "D:\\data.dat";
    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath));
    oos.write(100);
    oos.writeBoolean(true);
    oos.writeChar('a');
    oos.writeDouble(5.21);
    oos.writeUTF("IMUSTCTF");
    oos.writeObject(new Dog("旺财"));
    oos.close();
    System.out.println("数据序列化成功!");
}


反序列化演示:

dog类:


// Dog 需要实现Serializable接口才可以支持序列化操作
class Dog implements Serializable {
    private String name;
    private int age;
    public Dog(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;
    }
    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}


反序列化类:


/**
 * ObjectInputStream反序列化
 */
@Test
public void Input() throws IOException, ClassNotFoundException {
    String filePath = "D:\\data.dat";
    ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath));
    // 开始读取bat文件
    // 注意:读取顺序要和序列化时的顺序一致!
    System.out.println(ois.readInt());
    System.out.println(ois.readBoolean());
    System.out.println(ois.readChar());
    System.out.println(ois.readDouble());
    System.out.println(ois.readUTF());
    Object dog = ois.readObject();
    System.out.println(dog);
    // 访问dog的私有属性
    Dog dog1 = (Dog) dog;
    System.out.println(dog1.getName());
    // 关闭外层流
    ois.close();
}


对象处理流使用细节:🎈

  • 序列化的类要实现Serializable接口
  • 请按照序列化的顺序进行反序列化
  • 序列化的类中建议添加如下语句:(为了提高版本的兼容性)


@Serial
private static final long serialVersionUID = 1L;


序列化对象时,static和transient修饰的成员不会被序列化

序列化对象时,要求里面的属性也要实现序列化接口💫

序列化具有可继承性,父类实现了序列化,则其子类也会默认实现序列化🚲


6.转换流


InputStreamReader可以将InputStream字节流转换成Reader字符流


/**
 * InputStreamReader演示
 */
@Test
public void InputStreamReaderTest() throws IOException {
    String filePath = "D:\\hacker.txt";
    // FileInputStream转换为InputStreamReader
    InputStreamReader isr = new InputStreamReader(new FileInputStream(filePath), StandardCharsets.UTF_8);
    // 把InputStreamReader传入BufferedReader
    BufferedReader br = new BufferedReader(isr);
    String s = br.readLine();
    System.out.println(s);
    br.close();
}


OutputStreamWriter可以将OutputStream字节流转换成Writer字符流


/**
 * OutputStreamWriter
 */
@Test
public void OutputStreamWriterTest() throws IOException {
    String filePath = "D:\\hacker.txt";
    OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(filePath), "gbk");
    osw.write("hi,kiki!");
    osw.write("我是大河!");
    osw.close();
}


7.打印流


PrintStream是字节打印流,代码演示:


/**
 * 字节打印流
 */
@Test
public void PrintStreamTest() throws IOException {
    PrintStream out = System.out;
    // 默认情况下,PrintStream输出的位置是标准输出,即显示器
    out.println("hello!");
    out.write("你好哦".getBytes());
    // 可以修改打印流输出的位置
    // 比如修改打印位置为文件中
    System.setOut(new PrintStream("D:\\hacker.txt"));
    System.out.println("华仔华仔!");
    out.close();
}


PrintWriter是字符打印流,代码演示:


/**
 * 字符打印流
 */
@Test
public void PrintWriterTest() throws IOException {
    PrintWriter printWriter = new PrintWriter(System.out);
    printWriter.println("你好");
    // 可以修改打印流输出的位置
    // 比如修改打印位置为文件中
    PrintWriter pw = new PrintWriter(new FileWriter("D:\\hacker.txt"));
    pw.print("我在文件里");
    printWriter.close();
    pw.close();
}


8.配置文件Properties


对于一些不经常改变的配置数据,我们可以采用Properties文件进行保存,如保存数据库的连接信息:

请注意:配置文件的格式(键值对)

键值对之间不能有空格,值不需要使用双引号包裹!💫


ip=192.168.0.1
user=root
password=youarealoser


采用Properties类读文件


/**
 * 读取
 */
@Test
public void read() throws IOException {
    Properties properties = new Properties();
    // 加载配置文件
    properties.load(new FileReader("io\\mysql.properties"));
    // 把 k-v 显示在控制台
    properties.list(System.out);
    // 根据key获取值
    String password = properties.getProperty("password");
    System.out.println(password);
}


采用Properties类修改文件


/**
 * 修改
 */
@Test
public void write() throws IOException {
    Properties properties = new Properties();
    // 设置键值对
    // 如果键已经存在,则等价于修改键
    properties.setProperty("user","汤姆");
    properties.setProperty("passwd","youwillwin");
    // 存储键值对
    properties.store(new FileOutputStream("io\\mysql.properties"),"mysql test data");
}


修改后的配置文件内容:


#mysql test data
#Fri Aug 05 16:53:29 CST 2022
passwd=youwillwin
user=\u6C64\u59C6
相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
28天前
|
存储 Java
【IO面试题 四】、介绍一下Java的序列化与反序列化
Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。
|
4天前
|
安全 Java API
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
String常量池、String、StringBuffer、Stringbuilder有什么区别、List与Set的区别、ArrayList和LinkedList的区别、HashMap底层原理、ConcurrentHashMap、HashMap和Hashtable的区别、泛型擦除、ABA问题、IO多路复用、BIO、NIO、O、异常处理机制、反射
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
|
14天前
|
数据采集 Java 数据挖掘
Java IO异常处理:在Web爬虫开发中的实践
Java IO异常处理:在Web爬虫开发中的实践
|
27天前
|
Java 数据处理
Java IO 接口(Input)究竟隐藏着怎样的神秘用法?快来一探究竟,解锁高效编程新境界!
【8月更文挑战第22天】Java的输入输出(IO)操作至关重要,它支持从多种来源读取数据,如文件、网络等。常用输入流包括`FileInputStream`,适用于按字节读取文件;结合`BufferedInputStream`可提升读取效率。此外,通过`Socket`和相关输入流,还能实现网络数据读取。合理选用这些流能有效支持程序的数据处理需求。
24 2
|
28天前
|
XML 存储 JSON
【IO面试题 六】、 除了Java自带的序列化之外,你还了解哪些序列化工具?
除了Java自带的序列化,常见的序列化工具还包括JSON(如jackson、gson、fastjson)、Protobuf、Thrift和Avro,各具特点,适用于不同的应用场景和性能需求。
|
28天前
|
缓存 Java
【IO面试题 一】、介绍一下Java中的IO流
Java中的IO流是对数据输入输出操作的抽象,分为输入流和输出流,字节流和字符流,节点流和处理流,提供了多种类支持不同数据源和操作,如文件流、数组流、管道流、字符串流、缓冲流、转换流、对象流、打印流、推回输入流和数据流等。
【IO面试题 一】、介绍一下Java中的IO流
|
30天前
|
Java
"揭秘Java IO三大模式:BIO、NIO、AIO背后的秘密!为何AIO成为高并发时代的宠儿,你的选择对了吗?"
【8月更文挑战第19天】在Java的IO编程中,BIO、NIO与AIO代表了三种不同的IO处理机制。BIO采用同步阻塞模型,每个连接需单独线程处理,适用于连接少且稳定的场景。NIO引入了非阻塞性质,利用Channel、Buffer与Selector实现多路复用,提升了效率与吞吐量。AIO则是真正的异步IO,在JDK 7中引入,通过回调或Future机制在IO操作完成后通知应用,适合高并发场景。选择合适的模型对构建高效网络应用至关重要。
27 2
|
1月前
|
Java Android开发
解决Android编译报错:Unable to make field private final java.lang.String java.io.File.path accessible
解决Android编译报错:Unable to make field private final java.lang.String java.io.File.path accessible
85 1
|
1月前
|
存储 缓存 Java
15 Java IO流(File类+IO流+字节流+字符流+字节编码)
15 Java IO流(File类+IO流+字节流+字符流+字节编码)
41 3
|
24天前
|
NoSQL Java Redis
【Azure Spring Cloud】Java Spring Cloud 应用部署到Azure上后,发现大量的 java.lang.NullPointerException: null at io.lettuce.core.protocol.CommandHandler.writeSingleCommand(CommandHandler.java:426) at ... 异常
【Azure Spring Cloud】Java Spring Cloud 应用部署到Azure上后,发现大量的 java.lang.NullPointerException: null at io.lettuce.core.protocol.CommandHandler.writeSingleCommand(CommandHandler.java:426) at ... 异常