流-为序列化解释

流(Stream)是什么?

流(Stream)是 Java 中用来处理输入和输出(I/O)操作的基本抽象,它可以用来读取和写入数据。流分为两种:

  • 字节流(Byte Stream): 用于处理原始二进制数据,如文件、图片等。

  • 字符流(Character Stream): 用于处理字符数据,支持对字符数据的编码和解码。

在序列化和反序列化的过程中,我们主要使用 字节流 。特别是在将对象写入到文件、网络或数据库时,会用到 ObjectOutputStreamObjectInputStream 这两个类,它们分别属于字节流的一部分。

什么时候会用到流?

在实际开发中,流常用于以下几个场景:

1. 文件操作:
  • 读取和写入文件: 在开发中,常常需要将对象保存到文件中,或者从文件中读取对象数据。这时我们就会用到流,结合序列化来实现对象的持久化。

示例: 将对象写入文件:

复制代码
import java.io.*;

public class FileExample {
    public static void main(String[] args) throws IOException {
        Person person = new Person("Alice", 30);

        // 序列化:将对象写入文件
        FileOutputStream fileOut = new FileOutputStream("person.ser");
        ObjectOutputStream out = new ObjectOutputStream(fileOut);
        out.writeObject(person);  // 对象序列化到文件
        out.close();
        fileOut.close();

        // 反序列化:从文件读取对象
        FileInputStream fileIn = new FileInputStream("person.ser");
        ObjectInputStream in = new ObjectInputStream(fileIn);
        Person deserializedPerson = (Person) in.readObject();
        in.close();
        fileIn.close();

        System.out.println(deserializedPerson);
    }
}

在这个例子中,ObjectOutputStream 用来将 person 对象序列化并写入文件,而 ObjectInputStream 用来从文件中读取并反序列化回原始对象。

2. 网络传输:
  • 客户端与服务器之间的数据传输: 在分布式系统中,客户端和服务器之间需要通过网络传输数据。如果传输的是对象,那么对象必须先序列化为字节流,才能通过网络发送。接收端收到数据后再反序列化还原为对象。

示例: 假设有一个简单的客户端和服务器,客户端将对象发送给服务器:

复制代码
// 客户端发送对象
Socket socket = new Socket("localhost", 8080);
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
Person person = new Person("Bob", 25);
out.writeObject(person);  // 序列化对象并发送
out.close();
socket.close();

// 服务器接收对象
ServerSocket serverSocket = new ServerSocket(8080);
Socket clientSocket = serverSocket.accept();
ObjectInputStream in = new ObjectInputStream(clientSocket.getInputStream());
Person receivedPerson = (Person) in.readObject();  // 反序列化对象
System.out.println("Received person: " + receivedPerson);
in.close();
clientSocket.close();
serverSocket.close();

这个例子演示了如何通过 ObjectOutputStream 将一个对象通过网络发送给服务器,并使用 ObjectInputStream 从网络读取并反序列化对象。

3. 数据库存储(持久化)
  • 对象持久化: 在一些情况下,我们需要将对象的数据存储到数据库中。这时候,我们可能会使用流(通过序列化)来将对象转化为二进制数据,并存入数据库的 BLOB 字段(大二进制对象)。当需要读取对象时,再从数据库中获取二进制数据,通过反序列化将其恢复为 Java 对象。

示例: 假设我们需要将一个 Person 对象存储到数据库中的 BLOB 字段:

复制代码
// 将对象序列化并存储到数据库
String sql = "INSERT INTO persons (data) VALUES (?)";
PreparedStatement statement = connection.prepareStatement(sql);

ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(byteArrayOut);
out.writeObject(person);
byte[] personData = byteArrayOut.toByteArray();

statement.setBytes(1, personData);
statement.executeUpdate();

读取时,我们可以通过 ObjectInputStream 将字节流反序列化回对象:

复制代码
// 从数据库中读取对象并反序列化
String sql = "SELECT data FROM persons WHERE id = ?";
PreparedStatement statement = connection.prepareStatement(sql);
ResultSet rs = statement.executeQuery();

if (rs.next()) {
    byte[] personData = rs.getBytes("data");
    ByteArrayInputStream byteArrayIn = new ByteArrayInputStream(personData);
    ObjectInputStream in = new ObjectInputStream(byteArrayIn);
    Person person = (Person) in.readObject();
    System.out.println(person);
}
4. 会话管理:
  • 在 Web 应用中,使用 HttpSession 来保存用户的会话信息。在某些情况下(如保存用户对象),你可能需要将 Java 对象序列化成字节流存入会话中,或者从会话中读取并反序列化。

例如,存储用户登录信息:

复制代码
HttpSession session = request.getSession();
User user = new User("john", "password123");
session.setAttribute("user", user);  // 将对象存入会话,自动序列化

当需要使用该信息时,可以从会话中取出对象:

复制代码
User user = (User) session.getAttribute("user");  // 获取并反序列化对象

总结:

流主要用于以下几种场景:

  • 文件操作: 将对象存储到文件或从文件读取。

  • 网络传输: 通过网络发送和接收对象。

  • 数据库存储: 将对象序列化为字节流并存入数据库,或从数据库中读取字节流并反序列化。

  • 会话管理: 在 Web 应用中,将对象存储到用户会话中。

在这些场景中,使用 是为了处理数据的输入输出操作,而 序列化反序列化 则是将 Java 对象转换为字节流的关键技术。

相关推荐
韩曙亮几秒前
【Web APIs】浏览器本地存储 ② ( window.sessionStorage 本地存储常用 API 简介 | 代码示例 )
开发语言·前端·javascript·localstorage·sessionstorage·web apis·浏览器本地存储
郑州光合科技余经理几秒前
私有化B2B订货系统实战:核心模块设计与代码实现
java·大数据·开发语言·后端·架构·前端框架·php
chillxiaohan3 分钟前
GO学习踩坑记录
开发语言·学习·golang
2301_7644413311 分钟前
python实现罗斯勒吸引子(Rössler Attractor)
开发语言·数据结构·python·算法·信息可视化
探序基因12 分钟前
R语言-使用pheatmap函数画热图
开发语言·r语言
-凌凌漆-14 分钟前
【JS】var与let的区别
开发语言·前端·javascript
ExiFengs17 分钟前
Java使用策略模式实现多实体通用操作的优雅设计
java·开发语言·设计模式·策略模式
茶本无香17 分钟前
设计模式之三—工厂模式:灵活对象创建的艺术
java·开发语言·设计模式·工厂模式
超级无敌大学霸21 分钟前
c语言整型提升
c语言·开发语言
困惑阿三24 分钟前
利用 Flexbox 实现无需媒体查询(Media Queries)的自动响应式网格。
开发语言·前端·javascript