序列化和反序列化的详解

序列化: 就是把内存中的对象,转换成字节序列(或其他数据传输协议)以便于存储(持久化)和网络传输;

反序列化: 就是将收到字节序列(或其他数据传输协议)或者是硬盘的持久化数据,转换成内存中的对象。

像数据库驱动类,就不能序列化,因为序列化后,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、大数据学习面试资料,请扫码关注我的公众号:

 

 

posted @ 2021-08-11 10:47  大数据同盟会  阅读(508)  评论(0)    收藏  举报