哈喽,哈喽,大家好~ 我是你们的老朋友:保护小周ღ
今天给大家带来的是 【Java IO流】对象与字节流的序列化和反序列化,首先了解, 本次主题有啥实际应用, 学习 ByteArrayOutputStream / ByteArrayInputStream 字节数组流, ObjectOutputStream / ObjectInputStream 对象与字节流的序列化和反序列化 , 前者作为当期流的输出目的, 和数据来源, 一起来看看叭~
本期收录于博主的专栏:JavaSE_保护小周ღ的博客-CSDN博客
适用于编程初学者,感兴趣的朋友们可以订阅,查看其它 “JavaSE基础知识”。
更多精彩敬请期待:保护小周ღ *★,°*:.☆( ̄▽ ̄)/$:*.°★* ‘
对象与字节流的序列化和反序列化在 Java 开发中具有重要作用,主要用于将对象状态转换为字节流以便存储或传输。以下是它们的一些作用介绍:
作用
-
持久化存储:
- 将对象的状态保存到文件或数据库,以便在系统重启时恢复。
- 例如,将用户设置、游戏进度等信息保存到磁盘。
-
网络传输:
- 在分布式系统或者微服务架构中,通过网络发送对象,以实现远程通信。
- 例如,使用 RMI(远程方法调用)或者 gRPC 进行服务间调用时,需要传输对象。
-
深拷贝:
-
缓存:
一、处理字节数组的流类
ByteArrayOutputStream
和 ByteArrayInputStream
是 Java 中用于处理字节数组的流类,通常用于输入和输出操作。
1.1 ByteArrayOutputStream
功能
ByteArrayOutputStream
允许你将数据写入一个字节数组中,而不是直接写入文件或其他输出流。- 这个类提供了一个可动态扩展的字节数组,可以随时获取当前写入的数据。
用法
- 创建一个
ByteArrayOutputStream
流对象。 - 使用
write()
方法将字节写入到流中。 - 调用
toByteArray()
方法获取写入的字节数组。
java hljs">public class ByteArrayOutputStreamExample {public static void main(String[] args) {// 这种将流对象写在 try 中的写法, 这种结构确保在操作完成后,相关的资源(如流)会被自动关闭,从而避免内存泄漏。try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {String data = "Hello, World!";// getBytes() 方法就是将字符串转换为字节数组, 写入流对象bos.write(data.getBytes());// 获取字节数组byte[] byteArray = bos.toByteArray();System.out.println("Written bytes: " + new String(byteArray));} catch (Exception e) {e.printStackTrace();}}
}
1.2 ByteArrayInputStream
功能
ByteArrayInputStream
允许你从一个字节数组中读取数据。- 可以用来在内存中模拟输入流操作,方便进行数据处理。
用法
- 创建一个
ByteArrayInputStream
对象,并传入一个字节数组。 - 使用
read()
方法读取字节,或者使用read(byte[] b)
方法将数据读取到字节数组中。
java hljs">public class ByteArrayInputStreamExample {public static void main(String[] args) {byte[] inputData = "Hello, World!".getBytes();try (ByteArrayInputStream bis = new ByteArrayInputStream(inputData)) {int data;int count = 0;while ((data = bis.read()) != -1) {count++;System.out.print((char) data); // 转换为字符并打印}System.out.println();// 说明一次读取四个字节, 但是也需要读取 13 次, Hello, World! 13个字符System.out.println(count);} catch (Exception e) {e.printStackTrace();}}
}
二、序列化与反序列化的流类
ObjectOutputStream
和 ObjectInputStream
是 Java 中用于对象的序列化与反序列化的流类。这两个类使得将对象写入流并从流中读取对象变得非常简单。
2.1 ObjectOutputStream
功能
ObjectOutputStream
可用于将 Java 对象序列化为字节流,以便存储或通过网络传输。- 它将对象的状态(包括对象的属性)转换为字节序列。
用法
- 创建一个
FileOutputStream(文件流)
以指定输出目的地(如文件)。 - 创建一个
ByteArrayOutputStream(字节数组)
就可以输出到字节数组啦。 - 使用
ObjectOutputStream
将对象写入到流中。 - 调用
writeObject()
方法将对象序列化。
java hljs">public class Person implements Serializable { //一定要实现Serializable 接口才可以序列化和反序列化private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Person{name='" + name + "', age=" + age + "}";}
}
java hljs">public class ObjectOutputStreamExample {public static void main(String[] args) {try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); // 序列化后往哪个流里面写, 也可以是 FileOutputSteamObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream)) { // 这种写法可以自动关闭资源Person person = new Person("Alice", 30);objectOutputStream.writeObject(person); // 序列化对象System.out.println("Object serialized: " + person);// 存储在字节数据流中, 以字节数组的形式输出System.out.println(Arrays.toString(byteArrayOutputStream.toByteArray()));} catch (Exception e) {e.printStackTrace();}}
}
2.2 ObjectInputStream
功能
用法
- 创建一个
FileInputStream
(文件流) 指向序列化对象的文件。 - 创建一个
ByteArrayInputStream(字节数组)
指向序列化对象的字节数组流。 - 使用
ObjectInputStream
从流中读取对象。 - 调用
readObject()
方法获取对象。
java hljs">public class ObjectInputStreamExample {public static void main(String[] args) {// 用于存储 Person 对象序列化后字节byte[] personBytes = new byte[0];// 1. 先将 Person 对象序列化为字节数组try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream)) { // 这种写法可以自动关闭资源Person person = new Person("Alice", 30);objectOutputStream.writeObject(person); // 序列化对象System.out.println("Object serialized: " + person);// 存储在字节数据流中, 以字节数组的形式输出byte[] data = byteArrayOutputStream.toByteArray();personBytes = new byte[data.length];personBytes = byteArrayOutputStream.toByteArray();System.out.println(Arrays.toString(personBytes));} catch (Exception e) {e.printStackTrace();}// 2. 将字节数组personBytes, 反序列化为 person 对象try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(personBytes); // 从哪个字节数组中读取ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream)) {Person person = (Person) objectInputStream.readObject();// 反序列化对象System.out.println("----------------------------------");System.out.println("Object deserialized: " + person);} catch (Exception e) {e.printStackTrace();}}
}
总结
这两个类主要用于持久化对象,确保对象状态可以在不同的程序运行间保存和恢复。注意,参与序列化的对象必须实现
Serializable
接口。且序列化/ 反序列化的字节流也可以使用 FileOutputStream 和 FileInputStream (文件流)来作为输出目的地和恢复的源头.
三、封装工具类
根据上述所讲, 我们可以将一个对象序列化为字节流, 也可以将字节流序列化为对象. 那我们就可以在开发中针对上述方法进行封装使用.
java hljs">/*** Created with IntelliJ IDEA.* Description: 二进制序列化工具* Author: 保护小周* Date: 2024-08-21* Time: 23:22*/
public class BinaryTool {/*** 把一个对象序列化成一个字节数组* @param object* @return*/public static byte[] toBytes(Object object) throws IOException {// 这个流对象相当于一个变长的字节数组.// 就可以把 object 序列化的数据给逐渐的写入到 byteArrayOutputStream 中, 再统一转成 byte[]try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream)) {// 此处的 writeObject 就会把该对象进行序列化, 生成的二进制字节数据, 就会写入到// ObjectOutputStream 中.// 由于 ObjectOutputStream 又是关联到了 ByteArrayOutputStream, 最终结果就写入到 ByteArrayOutputStream 里了objectOutputStream.writeObject(object);}// 这个操作就是把 byteArrayOutputStream 中持有的二进制数据取出来, 转成 byte[]return byteArrayOutputStream.toByteArray();}}/*** 把一个字节数组, 反序列化成一个对象* @param data* @return*/public static Object fromBytes(byte[] data) throws IOException, ClassNotFoundException {Object object = null;// 这个流对象相当于一个边长的字节数组// 就可以把object 序列化的数据给逐渐的写入到 byteArrayOutStream.try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(data)) {try (ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream)) {// 此处的 readObject 就是从 data 这个 byte[] 中读取数据并进行反序列化.object = objectInputStream.readObject();}}return object;}
}
实际应用效果展示: 非常的实用呀~
好了,到这里,【Java IO流】对象与字节流的序列化和反序列化 博主已经分享完了,阐述较为基础, 希望对大家有所帮助,如有不妥之处欢迎批评指正。
感谢每一位观看本篇文章的朋友,更多精彩敬请期待:保护小周ღ *★,°*:.☆( ̄▽ ̄)/$:*.°★*
遇见你,所有的星星都落在我的头上……