java序列化/反序列化之xml、protobuf、protostuff 的比较与使用例子

摘要:
1.4.生成的文件大小:protostuff占据最少,protobuf占据第二位,xml占据最后一位,前两位约为后者的1/4。
目录

1、背景

2、测试

  2.1、环境

  2.2、工具

  2.3、说明

  2.4、结果

  2.5、结论

3、xml简单教程

  3.1、准备

  3.2、代码 

4、protobuf简单教程

  4.1、快速入门

    1、下载.exe编译器

    2、编写.proto文件

    3、利用编译器编译.proto文件生成javabean

    4、引用jar包

    5、直接使用javabean自带的序列化、反序列化、提取属性等方法

5、protostuff简单教程

  5.1、快速入门

    1、引用jar包

    2、直接使用相关序列化、反序列化语法

 6、protobuf与protostuff区别

protostuff是一个基于protobuf实现的序列化方法,它较于protobuf最明显的好处是,在几乎不损耗性能的情况下做到了不用我们写.proto文件来实现序列化。

1、背景

 我今天要将的是google开发的开源的序列化方案protocol buffer(简称protobuf),它的好处很多,独立于语言,独立于平台,最最重要的是它的效率相当高,用protobuf序列化后的大小是json的10分之一,xml格式的20分之一,是二进制序列化的10分之一。

2、测试

2.1 测试环境

java序列化/反序列化之xml、protobuf、protostuff 的比较与使用例子第1张

xstraem版本:1.3.1

protobuf-java版本:3.0.0-alpha-2

java版本:1.7

-Xms2048m

-Xmx2048m

2.2 测试工具

用时: 控制台输出时间

CPU&内存: jconsole

文件大小: 文件属性

2.3 说明

测试中,xml和protoBuf和protostuff三种测试所使用的JavaBean所拥有的字段类型相同、字段数量相同(约28个)、字段所附的值相同、都包含有一个List<String>字段,用List字段的size来控制JavaBean对象的大小。本次测试中size=100

2.4  结果

测试A:10000个对象

 

Xml

protobuf

protostuff

序列化

用时(ms)

2399

648

261

占用的CPU(%)

24.2

12.3

3.4

占用的内存(M)

154

235

92

每个文件大小(byte)

2822

574

574

反序列化

用时(ms)

3378

167

224

占用CPU(%)

15.9

14.2

6.1

占用内存(M)

248

307

164

备注:10000个对象

测试B:25000个对象

 

Xml

protobuf

protostuff

序列化

用时(ms)

4161

767

293

占用的CPU(%)

31.2

14.6

4.7

占用的内存(M)

495

228

194

每个文件大小(byte)

2822

574

574

反序列化

用时(ms)

6941

252

393

占用CPU(%)

31.9

21.9

8.1

占用内存(M)

411

382

348

备注:25000个对象

测试C:100000个对象

 

Xml

protobuf

protostuff

序列化

用时(ms)

12867

3070

704

占用的CPU(%)

42.5

44.9

22.3

占用的内存(M)

1098

1058

572

每个文件大小(byte)

2822

574

574

反序列化

用时(ms)

24442

4540

1522

占用CPU(%)

38.8

68.2

24.1

占用内存(M)

2215

597

870

备注:50000个对象

2.5 结论

1、序列化:

  1.1、速度上:protostuff比protobuf快3倍左右,protobuf比xml快4-5倍,该倍数随着序列化对象的增加,基本保持不变。

  1.2、CPU上:protostuff占用最少,protobuf其次,xml最后。

  1.3、内存上:protostuff占用最少,protobuf其次,xml最后。

  1.4、生成文件大小:protostuff占用最少,protobuf其次,xml最后,前面两者是后者的1/4左右。

2、反序列化

  2.1、速度上:在反序列化对象数量较少的情况下,protobuf比protostuff快1/4左右,比xml快10+倍。但随着对象数量的增加,protobuf发生了速率明显变慢的情况!从而被protostuff赶超。

  2.2、CPU上:protostuff占用最少,protobuf其次,xml最后。

  2.3、内存上:protostuff占用最少,protobuf其次,xml最后。

3、总结

  在各个方面上,protostuff的优势非常面试,而protobuf也不弱,考虑用来代替xml。

3、xml简单教程

3.1 准备

jar包:pom.xml:

        <!-- xstream -->
        <dependency>
            <groupId>com.thoughtworks.xstream</groupId>
            <artifactId>xstream</artifactId>
            <version>1.3.1</version>
        </dependency>

 3.2 代码

1、java bean:

java序列化/反序列化之xml、protobuf、protostuff 的比较与使用例子第2张java序列化/反序列化之xml、protobuf、protostuff 的比较与使用例子第3张
package com.dxz.serializable;

import java.util.List;

/**
 * 商品类
 */
public class Products {

    private String s1;
    private String s2;
    private String s3;
    private String s4;
    private String s5;
    private String s6;
    private String s7;
    private String s8;
    private String s9;

    private int i1;
    private int i2;
    private int i3;
    private int i4;
    private int i5;
    private int i6;
    private int i7;
    private int i8;
    private int i9;

    private boolean b1;
    private boolean b2;
    private boolean b3;
    private boolean b4;
    private boolean b5;
    private boolean b6;
    private boolean b7;
    private boolean b8;
    private boolean b9;

    private List<String> list;

    public String getS1() {
        return s1;
    }

    public void setS1(String s1) {
        this.s1 = s1;
    }

    public String getS2() {
        return s2;
    }

    public void setS2(String s2) {
        this.s2 = s2;
    }

    public String getS3() {
        return s3;
    }

    public void setS3(String s3) {
        this.s3 = s3;
    }

    public String getS4() {
        return s4;
    }

    public void setS4(String s4) {
        this.s4 = s4;
    }

    public String getS5() {
        return s5;
    }

    public void setS5(String s5) {
        this.s5 = s5;
    }

    public String getS6() {
        return s6;
    }

    public void setS6(String s6) {
        this.s6 = s6;
    }

    public String getS7() {
        return s7;
    }

    public void setS7(String s7) {
        this.s7 = s7;
    }

    public String getS8() {
        return s8;
    }

    public void setS8(String s8) {
        this.s8 = s8;
    }

    public String getS9() {
        return s9;
    }

    public void setS9(String s9) {
        this.s9 = s9;
    }

    public int getI1() {
        return i1;
    }

    public void setI1(int i1) {
        this.i1 = i1;
    }

    public int getI2() {
        return i2;
    }

    public void setI2(int i2) {
        this.i2 = i2;
    }

    public int getI3() {
        return i3;
    }

    public void setI3(int i3) {
        this.i3 = i3;
    }

    public int getI4() {
        return i4;
    }

    public void setI4(int i4) {
        this.i4 = i4;
    }

    public int getI5() {
        return i5;
    }

    public void setI5(int i5) {
        this.i5 = i5;
    }

    public int getI6() {
        return i6;
    }

    public void setI6(int i6) {
        this.i6 = i6;
    }

    public int getI7() {
        return i7;
    }

    public void setI7(int i7) {
        this.i7 = i7;
    }

    public int getI8() {
        return i8;
    }

    public void setI8(int i8) {
        this.i8 = i8;
    }

    public int getI9() {
        return i9;
    }

    public void setI9(int i9) {
        this.i9 = i9;
    }

    public boolean isB1() {
        return b1;
    }

    public void setB1(boolean b1) {
        this.b1 = b1;
    }

    public boolean isB2() {
        return b2;
    }

    public void setB2(boolean b2) {
        this.b2 = b2;
    }

    public boolean isB3() {
        return b3;
    }

    public void setB3(boolean b3) {
        this.b3 = b3;
    }

    public boolean isB4() {
        return b4;
    }

    public void setB4(boolean b4) {
        this.b4 = b4;
    }

    public boolean isB5() {
        return b5;
    }

    public void setB5(boolean b5) {
        this.b5 = b5;
    }

    public boolean isB6() {
        return b6;
    }

    public void setB6(boolean b6) {
        this.b6 = b6;
    }

    public boolean isB7() {
        return b7;
    }

    public void setB7(boolean b7) {
        this.b7 = b7;
    }

    public boolean isB8() {
        return b8;
    }

    public void setB8(boolean b8) {
        this.b8 = b8;
    }

    public boolean isB9() {
        return b9;
    }

    public void setB9(boolean b9) {
        this.b9 = b9;
    }

    public List<String> getList() {
        return list;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

    public Products() {

    }

    public Products(String s1, String s2, String s3, String s4, String s5, String s6, String s7, String s8, String s9,
            int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, boolean b1, boolean b2, boolean b3,
            boolean b4, boolean b5, boolean b6, boolean b7, boolean b8, boolean b9, List<String> list) {
        super();
        this.s1 = s1;
        this.s2 = s2;
        this.s3 = s3;
        this.s4 = s4;
        this.s5 = s5;
        this.s6 = s6;
        this.s7 = s7;
        this.s8 = s8;
        this.s9 = s9;
        this.i1 = i1;
        this.i2 = i2;
        this.i3 = i3;
        this.i4 = i4;
        this.i5 = i5;
        this.i6 = i6;
        this.i7 = i7;
        this.i8 = i8;
        this.i9 = i9;
        this.b1 = b1;
        this.b2 = b2;
        this.b3 = b3;
        this.b4 = b4;
        this.b5 = b5;
        this.b6 = b6;
        this.b7 = b7;
        this.b8 = b8;
        this.b9 = b9;
        this.list = list;
    }

    @Override
    public String toString() {
        return "Products [s1=" + s1 + ", s2=" + s2 + ", s3=" + s3 + ", s4=" + s4 + ", s5=" + s5 + ", s6=" + s6 + ", s7="
                + s7 + ", s8=" + s8 + ", s9=" + s9 + ", i1=" + i1 + ", i2=" + i2 + ", i3=" + i3 + ", i4=" + i4 + ", i5="
                + i5 + ", i6=" + i6 + ", i7=" + i7 + ", i8=" + i8 + ", i9=" + i9 + ", b1=" + b1 + ", b2=" + b2 + ", b3="
                + b3 + ", b4=" + b4 + ", b5=" + b5 + ", b6=" + b6 + ", b7=" + b7 + ", b8=" + b8 + ", b9=" + b9
                + ", list=" + list + "]";
    }
}
View Code

2、序列化:

public  List<String> serializeXMLProductsList(List<Products> pList) {
        if(pList == null) {
            System.out.println("【XmlSerializeServiceImpl-serializeProductsListService】pList参数为空");
            return null;
        }
        long start = System.currentTimeMillis() ;
        XStream x = new XStream();
        x.alias("Products", Products.class);
        List<String> strList = new ArrayList<String>();
        for(Products p : pList) {
            String str = x.toXML(p);
            strList.add(str);
        }
        long end = System.currentTimeMillis() ;
        usedTime = end - start ;
        return strList;
    }

    public List<Products> deserializeXMLDataListToProductsList(
            List<String> xmlStrList) {
        long start = System.currentTimeMillis();
        List<Products> productsList = new ArrayList<Products>();
        XStream xs = new XStream();
        xs.alias("Products", Products.class);
        for(String xmlStr : xmlStrList) {
            Products p = (Products)xs.fromXML(xmlStr);
            productsList.add(p);
        }
        long end = System.currentTimeMillis();
        usedTime = end - start ; 
        return productsList;
    }

然而,一般来说,对xstream的序列化和反序列化,要自己实现Converter接口来转化的,这样的解决一个问题,就是对方接口的字段和我们自己的javabean的字段名不一致的问题。这里不多说,可以搜索xstrem Converter,即有大量文章。

4、protobuf简单教程

4.1、快速入门:

  下载.exe编译器——编写.proto文件——利用编译器编译.proto文件生成javabean——引用jar包——直接使用javabean自带的序列化、反序列化方法

1、下载针对java的.exe编译器

protobuf编译器官方下载地址:https://developers.google.com/protocol-buffers/docs/downloads

下载不了的:点我

2、编写.proto文件,如下Products.proto文件

package tutorial;
option java_package = "com.dxz.serializable";
option java_outer_classname = "Products2"; 
message Products22 { 
  required string s1 = 1;
  required string s2 = 2;
  required string s3 = 3;
  required string s4 = 4;
  required string s5 = 5;
  required string s6 = 6;
  required string s7 = 7;
  required string s8 = 8;
  required string s9 = 9;
  required int32 i10 = 10;
  required int32 i11 = 11;
  required int32 i12 = 12;
  required int32 i13 = 13;
  required int32 i14 = 14;
  required int32 i15 = 15;
  required int32 i16 = 16;
  required int32 i17 = 17;
  required int32 i18 = 18;
  required bool b19 = 19;
  required bool b20 = 20;
  required bool b21 = 21;
  required bool b22 = 22;
  required bool b23 = 23;
  required bool b24 = 24;
  required bool b25 = 25;
  required bool b26 = 26;
  required bool b27 = 27;
  repeated string list = 28;
}

其中的option java_package代表将要生成的javabean所有的包的包名

其中的option java_outer_classname代表要生成的javabean的类名

其中的message Products22可以理解为一个类似C语言的结构体,在生成的javabean中将变成一个内部类,一个.proto文件可以有无数个message 

proto支持的类型与修饰符可参考该博客:http://blog.sina.com.cn/s/blog_abea023b0101dxce.html

3、利用编译器编译.proto文件生成javabean

把.proto文件放在.exe同个目录下面,打开cmd,进入同目录下,执行命令:

protoc.exe --java_out=./ Products.proto

java序列化/反序列化之xml、protobuf、protostuff 的比较与使用例子第4张

假如.proto文件没有编写错误的话,成功后在同目录下即有javabean的类生成。

4、引用jar包

jar包地址pom.xml:

       <!-- protobuf -->
        <dependency>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java</artifactId>
            <version>3.0.0-alpha-2</version>
        </dependency>

5、把刚刚生成的javabean复制到项目中,这里直接使用javabean自带的序列化、反序列化方法

刚刚生成的javabean为:Products2

序列化例子:

public List<byte[]> serializeProtoBufProductsList(
            List<Builder> builderList) {
        if(builderList == null) {
            System.out.println("【ProtoBufSerializeServiceImpl-serializeProtoBufProductsService】builderList==null");
        }
        long start = System.currentTimeMillis();
        List<byte[]> bytesList = new ArrayList<byte[]>();
        for(Products2.Products22.Builder p22Builder : builderList){
            Products2.Products22 p22 = p22Builder.build();
            byte[] bytes = p22.toByteArray();
            bytesList.add(bytes);
        }
        long end = System.currentTimeMillis();
        usedTime = end - start ;
        return bytesList;
    }

builder对象由来:com.dxz.Products2.Products22.Builder,即可有生成的javabean点出来。

反序列化例子:

    public List<Products22> deserializeProtoBufDataListToProducts22List(
            List<byte[]> bytesList) {
        long start = System.currentTimeMillis();
        List<Products22> list = new ArrayList<Products22>();
        for(byte[] b : bytesList) {
            try {
                list.add(Products2.Products22.parseFrom(b));
            } catch (InvalidProtocolBufferException e) {
                e.printStackTrace();
            }
        }
        long end = System.currentTimeMillis();
        usedTime = end - start;
        return list;
    }

拿出具体字段例子:

                Products22 p = Products2.Products22.parseFrom(b);
                String s1 = p.getS1();
                int i1 = p.getI10();
                boolean b1 = p.getB19();
                ProtocolStringList l = p.getListList();
                
                for(String s : l) {
                    
                }
5、protostuff简单教程

 5.1 快速入门

  引用jar包——学习语法——直接使用

1、引用jar包:

pom.xml:

        <!-- protostuff -->
        <dependency>
            <groupId>com.dyuproject.protostuff</groupId>
            <artifactId>protostuff-core</artifactId>
            <version>1.0.7</version>
            <optional>true</optional>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.dyuproject.protostuff</groupId>
            <artifactId>protostuff-runtime</artifactId>
            <version>1.0.7</version>
            <optional>true</optional>
            <scope>provided</scope>
        </dependency>

2、javabean:

同上面xml的javabean

3、序列化例子:

public List<byte[]> serializeProtoStuffProductsList(List<Products> pList) {
        if(pList == null  ||  pList.size() <= 0) {
            return null;
        }
        long start = System.currentTimeMillis() ;
        List<byte[]> bytes = new ArrayList<byte[]>();
        Schema<Products> schema = RuntimeSchema.getSchema(Products.class);
        LinkedBuffer buffer = LinkedBuffer.allocate(4096);
        byte[] protostuff = null;
        for(Products p : pList) {
            try {
                protostuff = ProtostuffIOUtil.toByteArray(p, schema, buffer);
                bytes.add(protostuff);
            } finally {
                buffer.clear();
            }
        }
        long end = System.currentTimeMillis() ;
        this.userTime = end - start;
        System.out.println(this.userTime);
        return bytes;
    }

    public List<Products> deserializeProtoStuffDataListToProductsList(
            List<byte[]> bytesList) {
        if(bytesList == null || bytesList.size() <= 0) {
            return null;
        }
        long start = System.currentTimeMillis() ;
        Schema<Products> schema = RuntimeSchema.getSchema(Products.class);
        List<Products> list = new ArrayList<Products>();
        for(byte[] bs : bytesList) {
            Products product = new Products();
            ProtostuffIOUtil.mergeFrom(bs, product, schema);
            list.add(product);
        }
        long end = System.currentTimeMillis() ;
        this.userTime = end - start;
        return list;
    }

免责声明:文章转载自《java序列化/反序列化之xml、protobuf、protostuff 的比较与使用例子》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇openssl 学习之从证书中提取RSA公钥N 和 Eelement-ui el-tree竖向滚动条和横向滚动条问题下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

关于c++正则表达式的用法

本人最近在做一个项目,这个项目里面有一个功能是这样的,要求这个项目中提供搜索功能,简单的说,如果里面输入1-10 11,15,27,39这个字符串,那么你就要从中找到1,2,3,4,5,6,7,8,9,10和11,15,27,39等等这些数字。我考虑了很久,决定使用正则表达式来做,采用的原因有两点:其一,因为考虑到范围的问题(比如说位数不能超过三位)这样的...

android获取Mac地址和IP地址

获取Mac地址实际项目中测试了如下几种方法:(1)设备开通Wifi连接,获取到网卡的MAC地址(但是不开通wifi,这种方法获取不到Mac地址,这种方法也是网络上使用的最多的方法) //根据Wifi信息获取本地Mac public static String getLocalMacAddressFromWifiInfo(Context cont...

Java:String和Date、Timestamp之间的转换

一、String与Date(java.util.Date)互转      1.1 String -> Date String dateStr = "2010/05/04 12:34:23";            Date date = new Date();            //注意format的格式要与日期String的格式相匹配  ...

02_编程规约——集合处理

1.【强制】关于hashCode和equals的处理,必须遵循如下规则 1.1 只要重写equals,就必须重写hashCode。 1.2 因为Set存储的是不重复对象,依据hashCode和equals进行判断,所以Set存储的对象必须重写这两个方法。 1.3 如果自定义对象为Map的键,那么必须重写hashCode和equals。 说明:String重...

从零搭建 ES 搜索服务(五)搜索结果高亮

一、前言 在实际使用中搜索结果中的关键词前端通常会以特殊形式展示,比如标记为红色使人一目了然。我们可以通过 ES 提供的高亮功能实现此效果。 二、代码实现 前文查询是通过一个继承 ElasticsearchRepository 的接口实现的,但是如果要实现高亮,这种方式就满足不了了,这里我们需要通过 ElasticsearchTemplate 来完成。...

分布式调度任务管理——Dkron(2)运行配置

一、Dkron——服务器配置信息 dkron 的命令行操作都以dkron 开头,后面可以跟着不同的配置信息,例如在命令行敲出以下命令 :dkron agent --server --bootstrap-expect= 1 表示dkron以代理服务器形式启动,并且提供数据中心中预期的服务器数量为1。 其他相关配置dkron agent信息如下: –adver...