基于 ObjectOutputStream 实现 对象与二进制数据 的序列化和反序列化

目录

为什么要进行序列化呢?

如何实现 对象与二进制数据 的序列化和反序列化?


为什么要进行序列化呢?


主要是为了把一个对象(结构化的数据)转化成一个 字符串 / 字节数组,方便我们存储(有时候需要将数据存储到文件中,而文件只能存 字符串 / 二进制数据,不方便直接存储 对象)和传输数据(通过网络传输).

如何实现 对象与二进制数据 的序列化和反序列化?


实际上针对二进制序列化也是有很多种方案的:

1. Java 标准库提供了序列化的方案,ObjectInputStream 和 ObjectOutputStream(推荐).

2. Hessian.

3. protobuffer

扫描二维码关注公众号,回复: 16729901 查看本文章

4. thrift.

5. 通过一些转化也可以使用 JSON 表示二进制数据(JSON 格式中有很多特殊符号:" {} 这些符号会影响 JSON 格式的解析):可以针对 二进制数据 进行 base64 编码. base64 的作用就是用 4 字节表示 3 个字节信息,会保证 4 个字节都是使用 文本字符(相当于是把 二进制数据转换成文本了, 就像是 HTML  中嵌入一个图片,就可以把图片的二进制 base64 编码 直接以文本的形式嵌入到 html 中),但是 base64 这种方案,效率低,有额外的转码开销,同时还会使空间变大.

Ps:这里我们使用方案一,也就是标准库自带的方案,这个方案最大的好处就是不必引入额外的依赖.

具体实现如下:

  1. 首先,如果想要这个对象能够序列化或者反序列化,就需要这个类能实现 Serializable 接口(无需重写任何方法)
  2. ByteArrayOutputStream:把 对象 序列化成 字节数组,流对象就相当于是一个变长的字节数组,通过 object 序列化数据,然后逐渐写入到 ByteArrayOutputStream 中,再统一转化成 byte[] 即可.
  3. ByteArrayInputStream:把 字节数组 反序列化成 对象,将需要转化的二进制数据交给 byteArrayInputStream,再把 byteArrayInputStream 交给 ObjectInputStream ,然后通过 readObject 方法就可以反序列化成对象了.
public class BinaryTool {

    /**
     * 把一个对象序列化成一个字节数组
     * @param object
     * @return
     */
    public static byte[] toBytes(Object object) throws IOException {
        try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
            try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream)) {
                //此处 writeObject 就会把该对象进行序列化,生成的二进制字节数据,写入到 ObjectOutputStream 中
                //又由于 ObjectOutputStream 又关联到了 ByteArrayOutputStream,最终就写入到了 ByteArrayOutputStream
                objectOutputStream.writeObject(object);
            }
            return byteArrayOutputStream.toByteArray();
        }
    }

    /**
     * 把一个字节数组反序列化成对象
     * @param data
     * @return
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public static Object fromBytes(byte[] data) throws IOException, ClassNotFoundException {
        Object object = null;
        try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(data)) {
            try (ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream)) {
                //此处的 readObject 就是从 data 这个 byte 中读取数据并进行反序列化
                object = objectInputStream.readObject();
            }
        }
        return object;
    }

}

Ps:不要混淆输入和输出的概念

inputstream 和 outputstream 都是对流的定义,这两个操作的中心都是内存,所以要理解他们的区别,关键就是理解内存和其他容器的交换。

内存-------------》屏幕 outputstream
屏幕-------------》内存 inputstream

内存-------------》硬盘 outoutstream 之后进行写操作write 将内容写入硬盘文件中
硬盘-------------》内存 inputstream 之后进行读操作read 将内容从硬盘读出到内存中进行,然后对其进行操作。
 

猜你喜欢

转载自blog.csdn.net/CYK_byte/article/details/132265020