用遊戲來講序列化與反序列化機制
- 2022 年 6 月 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
Google推出,一種語言無關、平台無關、可擴展的序列化結構數據的方法,可用於通訊協議、數據存儲等。序列化後體積小,一般用於對傳輸性能有較高要求的系統。
了解不是很多,後面工作用到的話再來進行擴展。
JSON
在系統之間進行交互的時候很常用。
JSON 序列化方式生成的是一串有規則的字元串,可讀性強。是有規則的字元串,不跟任何程式語言綁定,天然上就具備了跨平台。
弊端:體積大。
常見的工具有:
fastJSON、Jackson、Gson 等。工作中比較常用的就是阿里的fastJSON,使用起來也很簡單,直接調用轉換的api即可,了解更多可以去官網看看。
各種序列化手段都有不同的特性,看你的業務再去選型。
序列化如何選擇
主要考慮三點:
-
選擇的序列化手段是否需要跨平台
-
選擇的序列化手段的速度要求
-


