• 欢迎光临~

用游戏来讲序列化与反序列化机制

开发技术 开发技术 2022-06-12 次浏览

一、写在最前

想象一下,你刚开始玩一个游戏,一进游戏,首先系统提示你需要创建一个角色。

新建角色对象:姓名(宇宙第一无敌厉害)谁会取这样的名字哈哈哈、性别、门派、等级......

建完角色之后,来到新手村,对于一个心怀大侠梦的有志青年当然不能被困在这小小的新手村了,所以你需要去刷boss攒经验升级。

boss对象:血量、等级、拥有技能......

就这样,经过不懈努力,你终于达到了能出新手村的等级。这时候,夜深了,你妈气急败坏叫你关电脑睡觉。大家都知道,创建的对象是保存在内存中的,内存中的数据断电即失。难道刚要出新手村,大侠梦就破灭了?怎么办呢?

二、大侠梦持续输出——序列化

为了不让无数青年的大侠梦关机即碎,序列化技术出现了,在游戏中的体现就是存档。即,在退出游戏的时候,点击存档按钮,这时候,你游戏角色的等级,装备等都会被保存在存储媒体中(硬盘等)。这时候,就算你关机了,下次再次登录游戏,还是你关机时保存的角色状态。

用游戏来讲序列化与反序列化机制

总结:序列化就是将内存中的对象数据存储到存储媒体中。

三、小爷我又回来了——反序列化

当天晚上,你在你妈的压迫下无奈关机睡觉了。第二天起来你迫不及待打开游戏准备再次大干一场,可是游戏角色已经被序列化到硬盘中,怎么取出来呢?这时候,反序列化技术就出现了。就是把你存在硬盘上的数据还原成原来的游戏对象,该是多少级还是多少级,该是啥装备就是啥装备。

总结:反序列化就是将存储在媒体中的对象还原成内存中对象。

序列化与反序列化扩展:

对于序列化来讲,不单单是作为将内存中的数据存储到媒体中,其网络传输也是一大作用。

你想想,玩游戏当然是大家一起玩才好了。每个游戏玩家在游戏世界中都可以进行沟通交流,当你刷boss的时候,爆到了一把一刀999的屠龙宝刀。这时候,你可以选择高价卖给游戏的其他土豪玩家。这时候,你不可能直接通过网线把这个给人家,而是通过序列化的方法,把这把屠龙刀传输给买家,买家在接收到这个数据之后,再通过反序列化将这把宝刀还原。

用游戏来讲序列化与反序列化机制

即,序列化的作用:

存储内存中的对象、进行网络传输。

四、序列化机制探究

上文说到,序列化可以进行网络传输,说到网络传输,那么I/O就不能陌生了,I/O传输支持的数据格式是字节数组。即,要想进行网络传输,就是将传输的对象转换成字节数组。但是,我们不能盲目随便转换成字节数组,因为你后面还需要将对象进行还原。也就是说,在进行转换的时候你要指定一个规则(序列化),在将对象转换成字节数组的时候按照这个规则进行转换。那个将对象进行还原的时候,按照规则(反序列化)进行还原。你不能将一个人偶拆了之后,装的时候,把手装成脚。

即,序列化机制:

将对象转换成字节数组的时候的转换规则,这种转换规则就是序列化机制。

用游戏来讲序列化与反序列化机制

五、序列化的种类

原生的JDK

JDK自带了序列化方法,只需要实现了Serializable接口的类,就可以通过ObjectOutputStream类将对象变成byte[]字节数组。

弊端:只能java自己玩。

代码示例:

/**
 * @ClassName Student
 * @Description Student类对象
 * @Author LH
 * @Date 2022/6/12 10:32
 */
@Data
public class Student implements Serializable {
    private String id;
    private String name;
    private int age;
}
/**
 * @ClassName JDKSerialize
 * @Description JDK序列化接口测试
 * @Author LH
 * @Date 2022/6/12 10:41
 */
public class JDKSerialize {

    /**
     *  对象序列化
     * @param  student 学生对象
     * @throws IOException 抛出io异常
     */
    public static void serializeStudent(Student student) throws IOException {
        ObjectOutputStream oo = new ObjectOutputStream(new ObjectOutputStream(Files.newOutputStream(new File("E:/java/workplace/study/student.txt").toPath())));
        oo.writeObject(student);
        oo.close();
    }

    /**
     * 对象反序列化
     * @param path 反序列化文件路径
     * @return Student 还原的学生对象
     * @throws IOException 抛出io异常
     * @throws ClassNotFoundException 找不到文件异常
     */
    public static Student deSerializeStudent(String path) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new ObjectInputStream(Files.newInputStream(new File(path).toPath())));
        Student student = (Student) ois.readObject();
        ois.close();
        return student;
    }

    public static void main(String[] args) {
        // 创建一个student对象
        Student student = new Student();
        student.setId("1");
        student.setName("LH");
        student.setAge(17);

        try {
            // 序列化student对象
            JDKSerialize.serializeStudent(student);
            // student对象饭序列化
            String path = "E:/java/workplace/study/student.txt";
            Student deSerializeStudent = JDKSerialize.deSerializeStudent(path);
            System.out.println("student id:" + deSerializeStudent.getId() + "student age:" + deSerializeStudent.getAge() + "student name:" + deSerializeStudent.getName());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

ProtoBuf

谷歌推出,一种语言无关、平台无关、可扩展的序列化结构数据的方法,可用于通信协议、数据存储等。序列化后体积小,一般用于对传输性能有较高要求的系统。

了解不是很多,后面工作用到的话再来进行扩展。

JSON

在系统之间进行交互的时候很常用。

JSON 序列化方式生成的是一串有规则的字符串,可读性强。是有规则的字符串,不跟任何编程语言绑定,天然上就具备了跨平台。

弊端:体积大。

常见的工具有:

fastJSONJacksonGson 等。工作中比较常用的就是阿里的fastJSON,使用起来也很简单,直接调用转换的api即可,了解更多可以去官网看看。

各种序列化手段都有不同的特性,看你的业务再去选型。

序列化如何选择

主要考虑三点:

  • 选择的序列化手段是否需要跨平台

  • 选择的序列化手段的速度要求

  • 选择的序列化手段的体积要求

程序员灯塔
转载请注明原文链接:用游戏来讲序列化与反序列化机制
喜欢 (0)