java serialize

版权声明:版权为ZZQ所有 https://blog.csdn.net/qq_39148187/article/details/81603684

可能最先接触的序列化莫过于就是学习io 的时候讲的Objectoutputstream /ObjectInputStream 了把, 实现serizlize 接口,这种方式是方便,但是他的效率,从内存占用来说确实不佳 ,我们这次拿java 的序列化,和google 提供的protobuf 比较, 算了把说说概念,什么是序列化在java 中?

序列化 :  把一个对象转换为2 字节数组,

反序列化就反过来嘛,序列化用于网络传输,tcp 传输的是2进制数字,对象如果想经过网路传输,比如经过序列化,如果用java api 提供的话就是实现serialize 接口我们先用 java 提供的api 序列化一次对象,代码如下

java Api Serialize

package com.zzq.serialize.java;

import java.io.Serializable;
import java.util.List;

/**
 * @author ZZQ
 * @date 2018/8/12 9:00
 */
public class Person  implements Serializable{

    private String name ;

    private Integer age ;

    private String sex ;


    public Person(String name, Integer age, String sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    public String getName() {

        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }


    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sex='" + sex + '\'' +
                '}';
    }
}
package com.zzq.serialize.java;

import java.io.*;
import java.util.Arrays;

/**
 * @author ZZQ
 * @date 2018/8/12 8:59
 *  传统java 的序列化
 */
public class Sserialize_java {

    public static void main(String[] args) throws  Exception {
        byte[] bytes = Object2ByteArray();
        Person person = byteArray2Object(bytes);
    }

    public  static  byte[] Object2ByteArray() throws  Exception{
        Person person = new Person("jack", 12, "男");
        ByteArrayOutputStream byteoutputStream = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteoutputStream);
        //把对象写入byteoutputStream 中
        objectOutputStream.writeObject(person);
        //获取字节数组
        byte[] byteArray = byteoutputStream.toByteArray();
        System.out.println(Arrays.toString(byteArray));
        System.out.println(byteArray.length);
        objectOutputStream.close();
        byteoutputStream.close();
        return  byteArray;
    }


    public static  Person byteArray2Object(byte[] arr) throws  Exception{
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(arr) ;
        ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
        Person p  =(Person) objectInputStream.readObject();
        System.out.println(p);
        return  p ;
    }


}

结果如下

我们可以看到用java 提供的api 实现序列化, 他的bytearray数组的长度是207 ,反序列化一切正常

protobuf serialize

ptotobuf 我感觉没有java 提供的api 简单使用,他首先要写proto 文件,然后通过程序生成java 对象,然后操作java 对象进行序列化,

说说proto 的语法把:

option java_package = "com.proto";

通过option java_package 定义包名, 这个东西对应生成java 对象的包名

option java_outer_classname = "PlayerModule";

option java_outer_classname 定义类名

注意: 这里的类名不是要序列化的对象的类名,是生成的java 文件的类名,该类中包含了要序列化的对象, 也就是你要使用的对象

然后我们来编写javabean

message PBPlayer{
	required int64 playerId = 1;
	
	required int32 age = 2;
	
	required string name = 3;
	
	repeated int32 skills = 4;
}

一个java 对象用message 定义, 相当于java 中的class 吧 ,

required 望文生义,这个就不言而喻了,意思就是必须赋值,不赋值就无法进行序列化,

int 32  64 这些参照这个表

.proto类型 Java 类型 C++类型 备注
double double double  
float float float  
int32 int int32 使用可变长编码方式。编码负数时不够高效——如果你的字段可能含有负数,那么请使用sint32。
int64 long int64 使用可变长编码方式。编码负数时不够高效——如果你的字段可能含有负数,那么请使用sint64。
uint32 int[1] uint32 Uses variable-length encoding.
uint64 long[1] uint64 Uses variable-length encoding.
sint32 int int32 使用可变长编码方式。有符号的整型值。编码时比通常的int32高效。
sint64 long int64 使用可变长编码方式。有符号的整型值。编码时比通常的int64高效。
fixed32 int[1] uint32 总是4个字节。如果数值总是比总是比228大的话,这个类型会比uint32高效。
fixed64 long[1] uint64 总是8个字节。如果数值总是比总是比256大的话,这个类型会比uint64高效。
sfixed32 int int32 总是4个字节。
sfixed64 long int64 总是8个字节。
bool boolean bool  
string String string 一个字符串必须是UTF-8编码或者7-bit ASCII编码的文本。
bytes ByteString string 可能包含任意顺序的字节数据。

目前 protobuf 提供三种语言支持 java py cpp 然后我把代码呈上

option java_package = "com.proto";
option java_outer_classname = "PlayerModule";

message PBPlayer{
	required int64 playerId = 1;
	
	required int32 age = 2;
	
	required string name = 3;
	
	repeated int32 skills = 4;
}

message PBResource{
	required int64 gold = 1;
	
	required int32 energy = 2;
}
package com.zzq.serialize.protobuf;

import java.lang.reflect.Array;
import java.util.Arrays;

/**
 * @author ZZQ
 * @date 2018/8/12 9:20
 *  使用protobuf 序列化
 */
public class serialize {

    public static void main(String[] args)  throws  Exception{
        byte[] bytes = Object2ByteArray();
        byteArrayToObject(bytes);
    }


    public  static  byte[] Object2ByteArray() throws  Exception{
        // 获取一个pbplayer构造器
        PlayerModule.PBPlayer.Builder builder = PlayerModule.PBPlayer.newBuilder();
        //设置数据
        builder.setAge(12).setName("jack").setPlayerId(110).addSkills(110);

        //构造出对象
        PlayerModule.PBPlayer build = builder.build();
        //序列化生成数组
        byte[] byteArray = build.toByteArray();
        System.out.println(Arrays.toString(byteArray));
        System.out.println(byteArray.length);
        return  byteArray;
    }


    public static  void  byteArrayToObject(byte[] bytes) throws  Exception{
        PlayerModule.PBPlayer pbPlayer = PlayerModule.PBPlayer.parseFrom(bytes);
        System.out.println(pbPlayer);
    }

}

结果i如下

大家可以看到 12  序列化后的bytearray 为12 相比 java 的api 他的内存占用小,内存占用小, 带宽占用的就少,大量的数据传输来说,同时间可以传输更多,效率就高

谢谢!

猜你喜欢

转载自blog.csdn.net/qq_39148187/article/details/81603684