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

一、写在最前

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

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

建完角色之后,来到新手村,对于一个心怀大侠梦的有志青年当然不能被困在这小小的新手村了,所以你需要去刷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即可,了解更多可以去官网看看。

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

序列化如何选择

主要考虑三点:

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

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

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

发表评论

相关文章