序列化和反序列化的詳解
阿新 • • 發佈:2021-08-11
序列化: 就是把記憶體中的物件,轉換成位元組序列(或其他資料傳輸協議)以便於儲存(持久化)和網路傳輸;
反序列化: 就是將收到位元組序列(或其他資料傳輸協議)或者是硬碟的持久化資料,轉換成記憶體中的物件。
像資料庫驅動類,就不能序列化,因為序列化後,localhost找不到地址,不能進行反序列化。
1、Java 序列化
是一個重量級序列化框架(Serializable),它會把這個物件的方方面面的資訊都序列化出去,產生的二進位制序列體積臃腫龐大,但是資訊很全。
public class SerDeDemo { public static void main(String[] args) throws Exception { Person p = new Person("周洋舟", 288899998.8, 18); // jdk中自帶的序列化工具,它會把這個物件的方方面面的資訊都序列化出去,產生的二進位制序列體積臃腫龐大,但是資訊很全 /*ObjectOutputStream objout = new ObjectOutputStream(new FileOutputStream("d:/p.obj")); objout.writeObject(p); objout.close();*/ DataOutputStream dataout = new DataOutputStream(new FileOutputStream("d:/p2.obj")); dataout.writeUTF(p.getName()); dataout.writeDouble(p.getSalary()); dataout.writeInt(p.getAge()); DataOutputStream dataout2 = new DataOutputStream(new FileOutputStream("d:/p3.obj")); dataout2.writeInt(18); dataout2.writeUTF("18"); } }
2、hadoop序列化
hadoop 自己開發了一套序列化機制(Writable),精簡、高效,需要實現write方法 和 readFields方法。
public class Person2 implements Writable { private String name; private Double salary; private int age; public Person2() { } public Person2(String name, Double salary, int age) { this.name = name; this.salary = salary; this.age = age; } public void write(DataOutput dataOutput) throws IOException { dataOutput.writeUTF(this.name); dataOutput.writeDouble(this.salary); //dataOutput.writeInt(this.age); } public void readFields(DataInput dataInput) throws IOException { this.name = dataInput.readUTF(); this.salary = dataInput.readDouble(); //this.age = dataInput.readInt(); } }
3、spark序列化
spark中將物件序列化,預設呼叫jdk的objectoutputstream(serializable),所以,我們在spark程式碼中,一般都要修改序列化器,可以用kryo序列化框架,kryo序列化框架的序列化結果要比jdk的序列化結果更精簡(少了一些類的元資訊)。
object SparkSerde { def main(args: Array[String]): Unit = { val spark1 = SparkSession.builder.config("spark.serializer", classOf[KryoSerializer].getName).appName("").master("local").getOrCreate import spark1.implicits._ spark1.createDataset(Seq(new Person("zz", 1888.8, 28))); // 上面的做法,kryo在序列化時,還是會帶上一些必要的類元資訊,以便於下游task能正確反序列化 // 下面的做法,可以提前將這些可能要被序列化的型別,註冊到kryo的對映表中,這樣,kryo在序列化時就不需要序列化類元資訊了 val conf = new SparkConf conf.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer") conf.registerKryoClasses(Array(classOf[Person],classOf[Person2])) val spark2 = SparkSession.builder() .config(conf) .master("local") .appName("序列化案例") .getOrCreate() } }
更多java、大資料學習面試資料,請掃碼關注我的公眾號:
專注於大資料和java開發,學習交流可以關注我的公眾號:javaydsj