Protocol Buffer序列化对比Java序列化.

时间:2022-04-24
本文章向大家介绍Protocol Buffer序列化对比Java序列化.,主要内容包括初识、proto对象、PB序列化、PB反序列化、Java序列化、Java反序列化、对比、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。

初识

Protocol Buff是谷歌推出的一种序列化协议. 而Java序列化协议也是一种协议.

两者的目的是, 将对象序列化成字节数组, 或者说是二进制数据, 那么他们之间有什么差异呢.

proto对象

要使用PB, 我们需要定义一个proto对象, 其支持的数据类型如下:

Protobuf定义了一套基本数据类型。几乎都可以映射到C++Java等语言的基础数据类型.

protobuf 数据类型

描述

打包

C++语言映射

bool

布尔类型

1字节

bool

double

64位浮点数

N

double

float

32为浮点数

N

float

int32

32位整数、

N

int

uin32

无符号32位整数

N

unsigned int

int64

64位整数

N

__int64

uint64

64为无符号整

N

unsigned __int64

sint32

32位整数,处理负数效率更高

N

int32

sing64

64位整数 处理负数效率更高

N

__int64

fixed32

32位无符号整数

4

unsigned int32

fixed64

64位无符号整数

8

unsigned __int64

sfixed32

32位整数、能以更高的效率处理负数

4

unsigned int32

sfixed64

64为整数

8

unsigned __int64

string

只能处理 ASCII字符

N

std::string

bytes

用于处理多字节的语言字符、如中文

N

std::string

enum

可以包含一个用户自定义的枚举类型uint32

N(uint32)

enum

message

可以包含一个用户自定义的消息类型

N

object of class

proto对象结构类似于java的class, 在同一个module里, 定义了两个类, PBPlayer 和 PBResource, 各自拥有一些成员变量.

 1 option java_package = "com.proto";
 2 option java_outer_classname = "PlayerModule";
 3 
 4 message PBPlayer{
 5     required int64 playerId = 1;
 6     
 7     required int32 age = 2;
 8     
 9     required string name = 3;
10     
11     repeated int32 skills = 4;
12 }
13 
14 message PBResource{
15     required int64 gold = 1;
16     
17     required int32 energy = 2;
18 }

然后用protoc.exe将proto对象转为java对象, 打开cmd, 运行如下命令:

1 protoc ./proto/*.proto --java_out=./src

生成的java对象比较庞大, 我们不需要细究里面代码, 直接调用即可.

   1 // Generated by the protocol buffer compiler.  DO NOT EDIT!
   2 // source: proto/player.proto
   3 
   4 package com.proto;
   5 
   6 public final class PlayerModule {
   7   private PlayerModule() {}
   8   public static void registerAllExtensions(
   9       com.google.protobuf.ExtensionRegistry registry) {
  10   }
  11   public interface PBPlayerOrBuilder
  12       extends com.google.protobuf.MessageOrBuilder {
  13     
  14     // required int64 playerId = 1;
  15     boolean hasPlayerId();
  16     long getPlayerId();
  17     
  18     // required int32 age = 2;
  19     boolean hasAge();
  20     int getAge();
  21     
  22     // required string name = 3;
  23     boolean hasName();
  24     String getName();
  25     
  26     // repeated int32 skills = 4;
  27     java.util.List<java.lang.Integer> getSkillsList();
  28     int getSkillsCount();
  29     int getSkills(int index);
  30   }
  31   public static final class PBPlayer extends
  32       com.google.protobuf.GeneratedMessage
  33       implements PBPlayerOrBuilder {
  34     // Use PBPlayer.newBuilder() to construct.
  35     private PBPlayer(Builder builder) {
  36       super(builder);
  37     }
  38     private PBPlayer(boolean noInit) {}
  39     
  40     private static final PBPlayer defaultInstance;
  41     public static PBPlayer getDefaultInstance() {
  42       return defaultInstance;
  43     }
  44     
  45     public PBPlayer getDefaultInstanceForType() {
  46       return defaultInstance;
  47     }
  48     
  49     public static final com.google.protobuf.Descriptors.Descriptor
  50         getDescriptor() {
  51       return com.proto.PlayerModule.internal_static_PBPlayer_descriptor;
  52     }
  53     
  54     protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
  55         internalGetFieldAccessorTable() {
  56       return com.proto.PlayerModule.internal_static_PBPlayer_fieldAccessorTable;
  57     }
  58     
  59     private int bitField0_;
  60     // required int64 playerId = 1;
  61     public static final int PLAYERID_FIELD_NUMBER = 1;
  62     private long playerId_;
  63     public boolean hasPlayerId() {
  64       return ((bitField0_ & 0x00000001) == 0x00000001);
  65     }
  66     public long getPlayerId() {
  67       return playerId_;
  68     }
  69     
  70     // required int32 age = 2;
  71     public static final int AGE_FIELD_NUMBER = 2;
  72     private int age_;
  73     public boolean hasAge() {
  74       return ((bitField0_ & 0x00000002) == 0x00000002);
  75     }
  76     public int getAge() {
  77       return age_;
  78     }
  79     
  80     // required string name = 3;
  81     public static final int NAME_FIELD_NUMBER = 3;
  82     private java.lang.Object name_;
  83     public boolean hasName() {
  84       return ((bitField0_ & 0x00000004) == 0x00000004);
  85     }
  86     public String getName() {
  87       java.lang.Object ref = name_;
  88       if (ref instanceof String) {
  89         return (String) ref;
  90       } else {
  91         com.google.protobuf.ByteString bs = 
  92             (com.google.protobuf.ByteString) ref;
  93         String s = bs.toStringUtf8();
  94         if (com.google.protobuf.Internal.isValidUtf8(bs)) {
  95           name_ = s;
  96         }
  97         return s;
  98       }
  99     }
 100     private com.google.protobuf.ByteString getNameBytes() {
 101       java.lang.Object ref = name_;
 102       if (ref instanceof String) {
 103         com.google.protobuf.ByteString b = 
 104             com.google.protobuf.ByteString.copyFromUtf8((String) ref);
 105         name_ = b;
 106         return b;
 107       } else {
 108         return (com.google.protobuf.ByteString) ref;
 109       }
 110     }
 111     
 112     // repeated int32 skills = 4;
 113     public static final int SKILLS_FIELD_NUMBER = 4;
 114     private java.util.List<java.lang.Integer> skills_;
 115     public java.util.List<java.lang.Integer>
 116         getSkillsList() {
 117       return skills_;
 118     }
 119     public int getSkillsCount() {
 120       return skills_.size();
 121     }
 122     public int getSkills(int index) {
 123       return skills_.get(index);
 124     }
 125     
 126     private void initFields() {
 127       playerId_ = 0L;
 128       age_ = 0;
 129       name_ = "";
 130       skills_ = java.util.Collections.emptyList();;
 131     }
 132     private byte memoizedIsInitialized = -1;
 133     public final boolean isInitialized() {
 134       byte isInitialized = memoizedIsInitialized;
 135       if (isInitialized != -1) return isInitialized == 1;
 136       
 137       if (!hasPlayerId()) {
 138         memoizedIsInitialized = 0;
 139         return false;
 140       }
 141       if (!hasAge()) {
 142         memoizedIsInitialized = 0;
 143         return false;
 144       }
 145       if (!hasName()) {
 146         memoizedIsInitialized = 0;
 147         return false;
 148       }
 149       memoizedIsInitialized = 1;
 150       return true;
 151     }
 152     
 153     public void writeTo(com.google.protobuf.CodedOutputStream output)
 154                         throws java.io.IOException {
 155       getSerializedSize();
 156       if (((bitField0_ & 0x00000001) == 0x00000001)) {
 157         output.writeInt64(1, playerId_);
 158       }
 159       if (((bitField0_ & 0x00000002) == 0x00000002)) {
 160         output.writeInt32(2, age_);
 161       }
 162       if (((bitField0_ & 0x00000004) == 0x00000004)) {
 163         output.writeBytes(3, getNameBytes());
 164       }
 165       for (int i = 0; i < skills_.size(); i++) {
 166         output.writeInt32(4, skills_.get(i));
 167       }
 168       getUnknownFields().writeTo(output);
 169     }
 170     
 171     private int memoizedSerializedSize = -1;
 172     public int getSerializedSize() {
 173       int size = memoizedSerializedSize;
 174       if (size != -1) return size;
 175     
 176       size = 0;
 177       if (((bitField0_ & 0x00000001) == 0x00000001)) {
 178         size += com.google.protobuf.CodedOutputStream
 179           .computeInt64Size(1, playerId_);
 180       }
 181       if (((bitField0_ & 0x00000002) == 0x00000002)) {
 182         size += com.google.protobuf.CodedOutputStream
 183           .computeInt32Size(2, age_);
 184       }
 185       if (((bitField0_ & 0x00000004) == 0x00000004)) {
 186         size += com.google.protobuf.CodedOutputStream
 187           .computeBytesSize(3, getNameBytes());
 188       }
 189       {
 190         int dataSize = 0;
 191         for (int i = 0; i < skills_.size(); i++) {
 192           dataSize += com.google.protobuf.CodedOutputStream
 193             .computeInt32SizeNoTag(skills_.get(i));
 194         }
 195         size += dataSize;
 196         size += 1 * getSkillsList().size();
 197       }
 198       size += getUnknownFields().getSerializedSize();
 199       memoizedSerializedSize = size;
 200       return size;
 201     }
 202     
 203     private static final long serialVersionUID = 0L;
 204     @java.lang.Override
 205     protected java.lang.Object writeReplace()
 206         throws java.io.ObjectStreamException {
 207       return super.writeReplace();
 208     }
 209     
 210     public static com.proto.PlayerModule.PBPlayer parseFrom(
 211         com.google.protobuf.ByteString data)
 212         throws com.google.protobuf.InvalidProtocolBufferException {
 213       return newBuilder().mergeFrom(data).buildParsed();
 214     }
 215     public static com.proto.PlayerModule.PBPlayer parseFrom(
 216         com.google.protobuf.ByteString data,
 217         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
 218         throws com.google.protobuf.InvalidProtocolBufferException {
 219       return newBuilder().mergeFrom(data, extensionRegistry)
 220                .buildParsed();
 221     }
 222     public static com.proto.PlayerModule.PBPlayer parseFrom(byte[] data)
 223         throws com.google.protobuf.InvalidProtocolBufferException {
 224       return newBuilder().mergeFrom(data).buildParsed();
 225     }
 226     public static com.proto.PlayerModule.PBPlayer parseFrom(
 227         byte[] data,
 228         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
 229         throws com.google.protobuf.InvalidProtocolBufferException {
 230       return newBuilder().mergeFrom(data, extensionRegistry)
 231                .buildParsed();
 232     }
 233     public static com.proto.PlayerModule.PBPlayer parseFrom(java.io.InputStream input)
 234         throws java.io.IOException {
 235       return newBuilder().mergeFrom(input).buildParsed();
 236     }
 237     public static com.proto.PlayerModule.PBPlayer parseFrom(
 238         java.io.InputStream input,
 239         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
 240         throws java.io.IOException {
 241       return newBuilder().mergeFrom(input, extensionRegistry)
 242                .buildParsed();
 243     }
 244     public static com.proto.PlayerModule.PBPlayer parseDelimitedFrom(java.io.InputStream input)
 245         throws java.io.IOException {
 246       Builder builder = newBuilder();
 247       if (builder.mergeDelimitedFrom(input)) {
 248         return builder.buildParsed();
 249       } else {
 250         return null;
 251       }
 252     }
 253     public static com.proto.PlayerModule.PBPlayer parseDelimitedFrom(
 254         java.io.InputStream input,
 255         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
 256         throws java.io.IOException {
 257       Builder builder = newBuilder();
 258       if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
 259         return builder.buildParsed();
 260       } else {
 261         return null;
 262       }
 263     }
 264     public static com.proto.PlayerModule.PBPlayer parseFrom(
 265         com.google.protobuf.CodedInputStream input)
 266         throws java.io.IOException {
 267       return newBuilder().mergeFrom(input).buildParsed();
 268     }
 269     public static com.proto.PlayerModule.PBPlayer parseFrom(
 270         com.google.protobuf.CodedInputStream input,
 271         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
 272         throws java.io.IOException {
 273       return newBuilder().mergeFrom(input, extensionRegistry)
 274                .buildParsed();
 275     }
 276     
 277     public static Builder newBuilder() { return Builder.create(); }
 278     public Builder newBuilderForType() { return newBuilder(); }
 279     public static Builder newBuilder(com.proto.PlayerModule.PBPlayer prototype) {
 280       return newBuilder().mergeFrom(prototype);
 281     }
 282     public Builder toBuilder() { return newBuilder(this); }
 283     
 284     @java.lang.Override
 285     protected Builder newBuilderForType(
 286         com.google.protobuf.GeneratedMessage.BuilderParent parent) {
 287       Builder builder = new Builder(parent);
 288       return builder;
 289     }
 290     public static final class Builder extends
 291         com.google.protobuf.GeneratedMessage.Builder<Builder>
 292        implements com.proto.PlayerModule.PBPlayerOrBuilder {
 293       public static final com.google.protobuf.Descriptors.Descriptor
 294           getDescriptor() {
 295         return com.proto.PlayerModule.internal_static_PBPlayer_descriptor;
 296       }
 297       
 298       protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
 299           internalGetFieldAccessorTable() {
 300         return com.proto.PlayerModule.internal_static_PBPlayer_fieldAccessorTable;
 301       }
 302       
 303       // Construct using com.proto.PlayerModule.PBPlayer.newBuilder()
 304       private Builder() {
 305         maybeForceBuilderInitialization();
 306       }
 307       
 308       private Builder(BuilderParent parent) {
 309         super(parent);
 310         maybeForceBuilderInitialization();
 311       }
 312       private void maybeForceBuilderInitialization() {
 313         if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
 314         }
 315       }
 316       private static Builder create() {
 317         return new Builder();
 318       }
 319       
 320       public Builder clear() {
 321         super.clear();
 322         playerId_ = 0L;
 323         bitField0_ = (bitField0_ & ~0x00000001);
 324         age_ = 0;
 325         bitField0_ = (bitField0_ & ~0x00000002);
 326         name_ = "";
 327         bitField0_ = (bitField0_ & ~0x00000004);
 328         skills_ = java.util.Collections.emptyList();;
 329         bitField0_ = (bitField0_ & ~0x00000008);
 330         return this;
 331       }
 332       
 333       public Builder clone() {
 334         return create().mergeFrom(buildPartial());
 335       }
 336       
 337       public com.google.protobuf.Descriptors.Descriptor
 338           getDescriptorForType() {
 339         return com.proto.PlayerModule.PBPlayer.getDescriptor();
 340       }
 341       
 342       public com.proto.PlayerModule.PBPlayer getDefaultInstanceForType() {
 343         return com.proto.PlayerModule.PBPlayer.getDefaultInstance();
 344       }
 345       
 346       public com.proto.PlayerModule.PBPlayer build() {
 347         com.proto.PlayerModule.PBPlayer result = buildPartial();
 348         if (!result.isInitialized()) {
 349           throw newUninitializedMessageException(result);
 350         }
 351         return result;
 352       }
 353       
 354       private com.proto.PlayerModule.PBPlayer buildParsed()
 355           throws com.google.protobuf.InvalidProtocolBufferException {
 356         com.proto.PlayerModule.PBPlayer result = buildPartial();
 357         if (!result.isInitialized()) {
 358           throw newUninitializedMessageException(
 359             result).asInvalidProtocolBufferException();
 360         }
 361         return result;
 362       }
 363       
 364       public com.proto.PlayerModule.PBPlayer buildPartial() {
 365         com.proto.PlayerModule.PBPlayer result = new com.proto.PlayerModule.PBPlayer(this);
 366         int from_bitField0_ = bitField0_;
 367         int to_bitField0_ = 0;
 368         if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
 369           to_bitField0_ |= 0x00000001;
 370         }
 371         result.playerId_ = playerId_;
 372         if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
 373           to_bitField0_ |= 0x00000002;
 374         }
 375         result.age_ = age_;
 376         if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
 377           to_bitField0_ |= 0x00000004;
 378         }
 379         result.name_ = name_;
 380         if (((bitField0_ & 0x00000008) == 0x00000008)) {
 381           skills_ = java.util.Collections.unmodifiableList(skills_);
 382           bitField0_ = (bitField0_ & ~0x00000008);
 383         }
 384         result.skills_ = skills_;
 385         result.bitField0_ = to_bitField0_;
 386         onBuilt();
 387         return result;
 388       }
 389       
 390       public Builder mergeFrom(com.google.protobuf.Message other) {
 391         if (other instanceof com.proto.PlayerModule.PBPlayer) {
 392           return mergeFrom((com.proto.PlayerModule.PBPlayer)other);
 393         } else {
 394           super.mergeFrom(other);
 395           return this;
 396         }
 397       }
 398       
 399       public Builder mergeFrom(com.proto.PlayerModule.PBPlayer other) {
 400         if (other == com.proto.PlayerModule.PBPlayer.getDefaultInstance()) return this;
 401         if (other.hasPlayerId()) {
 402           setPlayerId(other.getPlayerId());
 403         }
 404         if (other.hasAge()) {
 405           setAge(other.getAge());
 406         }
 407         if (other.hasName()) {
 408           setName(other.getName());
 409         }
 410         if (!other.skills_.isEmpty()) {
 411           if (skills_.isEmpty()) {
 412             skills_ = other.skills_;
 413             bitField0_ = (bitField0_ & ~0x00000008);
 414           } else {
 415             ensureSkillsIsMutable();
 416             skills_.addAll(other.skills_);
 417           }
 418           onChanged();
 419         }
 420         this.mergeUnknownFields(other.getUnknownFields());
 421         return this;
 422       }
 423       
 424       public final boolean isInitialized() {
 425         if (!hasPlayerId()) {
 426           
 427           return false;
 428         }
 429         if (!hasAge()) {
 430           
 431           return false;
 432         }
 433         if (!hasName()) {
 434           
 435           return false;
 436         }
 437         return true;
 438       }
 439       
 440       public Builder mergeFrom(
 441           com.google.protobuf.CodedInputStream input,
 442           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
 443           throws java.io.IOException {
 444         com.google.protobuf.UnknownFieldSet.Builder unknownFields =
 445           com.google.protobuf.UnknownFieldSet.newBuilder(
 446             this.getUnknownFields());
 447         while (true) {
 448           int tag = input.readTag();
 449           switch (tag) {
 450             case 0:
 451               this.setUnknownFields(unknownFields.build());
 452               onChanged();
 453               return this;
 454             default: {
 455               if (!parseUnknownField(input, unknownFields,
 456                                      extensionRegistry, tag)) {
 457                 this.setUnknownFields(unknownFields.build());
 458                 onChanged();
 459                 return this;
 460               }
 461               break;
 462             }
 463             case 8: {
 464               bitField0_ |= 0x00000001;
 465               playerId_ = input.readInt64();
 466               break;
 467             }
 468             case 16: {
 469               bitField0_ |= 0x00000002;
 470               age_ = input.readInt32();
 471               break;
 472             }
 473             case 26: {
 474               bitField0_ |= 0x00000004;
 475               name_ = input.readBytes();
 476               break;
 477             }
 478             case 32: {
 479               ensureSkillsIsMutable();
 480               skills_.add(input.readInt32());
 481               break;
 482             }
 483             case 34: {
 484               int length = input.readRawVarint32();
 485               int limit = input.pushLimit(length);
 486               while (input.getBytesUntilLimit() > 0) {
 487                 addSkills(input.readInt32());
 488               }
 489               input.popLimit(limit);
 490               break;
 491             }
 492           }
 493         }
 494       }
 495       
 496       private int bitField0_;
 497       
 498       // required int64 playerId = 1;
 499       private long playerId_ ;
 500       public boolean hasPlayerId() {
 501         return ((bitField0_ & 0x00000001) == 0x00000001);
 502       }
 503       public long getPlayerId() {
 504         return playerId_;
 505       }
 506       public Builder setPlayerId(long value) {
 507         bitField0_ |= 0x00000001;
 508         playerId_ = value;
 509         onChanged();
 510         return this;
 511       }
 512       public Builder clearPlayerId() {
 513         bitField0_ = (bitField0_ & ~0x00000001);
 514         playerId_ = 0L;
 515         onChanged();
 516         return this;
 517       }
 518       
 519       // required int32 age = 2;
 520       private int age_ ;
 521       public boolean hasAge() {
 522         return ((bitField0_ & 0x00000002) == 0x00000002);
 523       }
 524       public int getAge() {
 525         return age_;
 526       }
 527       public Builder setAge(int value) {
 528         bitField0_ |= 0x00000002;
 529         age_ = value;
 530         onChanged();
 531         return this;
 532       }
 533       public Builder clearAge() {
 534         bitField0_ = (bitField0_ & ~0x00000002);
 535         age_ = 0;
 536         onChanged();
 537         return this;
 538       }
 539       
 540       // required string name = 3;
 541       private java.lang.Object name_ = "";
 542       public boolean hasName() {
 543         return ((bitField0_ & 0x00000004) == 0x00000004);
 544       }
 545       public String getName() {
 546         java.lang.Object ref = name_;
 547         if (!(ref instanceof String)) {
 548           String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
 549           name_ = s;
 550           return s;
 551         } else {
 552           return (String) ref;
 553         }
 554       }
 555       public Builder setName(String value) {
 556         if (value == null) {
 557     throw new NullPointerException();
 558   }
 559   bitField0_ |= 0x00000004;
 560         name_ = value;
 561         onChanged();
 562         return this;
 563       }
 564       public Builder clearName() {
 565         bitField0_ = (bitField0_ & ~0x00000004);
 566         name_ = getDefaultInstance().getName();
 567         onChanged();
 568         return this;
 569       }
 570       void setName(com.google.protobuf.ByteString value) {
 571         bitField0_ |= 0x00000004;
 572         name_ = value;
 573         onChanged();
 574       }
 575       
 576       // repeated int32 skills = 4;
 577       private java.util.List<java.lang.Integer> skills_ = java.util.Collections.emptyList();;
 578       private void ensureSkillsIsMutable() {
 579         if (!((bitField0_ & 0x00000008) == 0x00000008)) {
 580           skills_ = new java.util.ArrayList<java.lang.Integer>(skills_);
 581           bitField0_ |= 0x00000008;
 582          }
 583       }
 584       public java.util.List<java.lang.Integer>
 585           getSkillsList() {
 586         return java.util.Collections.unmodifiableList(skills_);
 587       }
 588       public int getSkillsCount() {
 589         return skills_.size();
 590       }
 591       public int getSkills(int index) {
 592         return skills_.get(index);
 593       }
 594       public Builder setSkills(
 595           int index, int value) {
 596         ensureSkillsIsMutable();
 597         skills_.set(index, value);
 598         onChanged();
 599         return this;
 600       }
 601       public Builder addSkills(int value) {
 602         ensureSkillsIsMutable();
 603         skills_.add(value);
 604         onChanged();
 605         return this;
 606       }
 607       public Builder addAllSkills(
 608           java.lang.Iterable<? extends java.lang.Integer> values) {
 609         ensureSkillsIsMutable();
 610         super.addAll(values, skills_);
 611         onChanged();
 612         return this;
 613       }
 614       public Builder clearSkills() {
 615         skills_ = java.util.Collections.emptyList();;
 616         bitField0_ = (bitField0_ & ~0x00000008);
 617         onChanged();
 618         return this;
 619       }
 620       
 621       // @@protoc_insertion_point(builder_scope:PBPlayer)
 622     }
 623     
 624     static {
 625       defaultInstance = new PBPlayer(true);
 626       defaultInstance.initFields();
 627     }
 628     
 629     // @@protoc_insertion_point(class_scope:PBPlayer)
 630   }
 631   
 632   public interface PBResourceOrBuilder
 633       extends com.google.protobuf.MessageOrBuilder {
 634     
 635     // required int64 gold = 1;
 636     boolean hasGold();
 637     long getGold();
 638     
 639     // required int32 energy = 2;
 640     boolean hasEnergy();
 641     int getEnergy();
 642   }
 643   public static final class PBResource extends
 644       com.google.protobuf.GeneratedMessage
 645       implements PBResourceOrBuilder {
 646     // Use PBResource.newBuilder() to construct.
 647     private PBResource(Builder builder) {
 648       super(builder);
 649     }
 650     private PBResource(boolean noInit) {}
 651     
 652     private static final PBResource defaultInstance;
 653     public static PBResource getDefaultInstance() {
 654       return defaultInstance;
 655     }
 656     
 657     public PBResource getDefaultInstanceForType() {
 658       return defaultInstance;
 659     }
 660     
 661     public static final com.google.protobuf.Descriptors.Descriptor
 662         getDescriptor() {
 663       return com.proto.PlayerModule.internal_static_PBResource_descriptor;
 664     }
 665     
 666     protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
 667         internalGetFieldAccessorTable() {
 668       return com.proto.PlayerModule.internal_static_PBResource_fieldAccessorTable;
 669     }
 670     
 671     private int bitField0_;
 672     // required int64 gold = 1;
 673     public static final int GOLD_FIELD_NUMBER = 1;
 674     private long gold_;
 675     public boolean hasGold() {
 676       return ((bitField0_ & 0x00000001) == 0x00000001);
 677     }
 678     public long getGold() {
 679       return gold_;
 680     }
 681     
 682     // required int32 energy = 2;
 683     public static final int ENERGY_FIELD_NUMBER = 2;
 684     private int energy_;
 685     public boolean hasEnergy() {
 686       return ((bitField0_ & 0x00000002) == 0x00000002);
 687     }
 688     public int getEnergy() {
 689       return energy_;
 690     }
 691     
 692     private void initFields() {
 693       gold_ = 0L;
 694       energy_ = 0;
 695     }
 696     private byte memoizedIsInitialized = -1;
 697     public final boolean isInitialized() {
 698       byte isInitialized = memoizedIsInitialized;
 699       if (isInitialized != -1) return isInitialized == 1;
 700       
 701       if (!hasGold()) {
 702         memoizedIsInitialized = 0;
 703         return false;
 704       }
 705       if (!hasEnergy()) {
 706         memoizedIsInitialized = 0;
 707         return false;
 708       }
 709       memoizedIsInitialized = 1;
 710       return true;
 711     }
 712     
 713     public void writeTo(com.google.protobuf.CodedOutputStream output)
 714                         throws java.io.IOException {
 715       getSerializedSize();
 716       if (((bitField0_ & 0x00000001) == 0x00000001)) {
 717         output.writeInt64(1, gold_);
 718       }
 719       if (((bitField0_ & 0x00000002) == 0x00000002)) {
 720         output.writeInt32(2, energy_);
 721       }
 722       getUnknownFields().writeTo(output);
 723     }
 724     
 725     private int memoizedSerializedSize = -1;
 726     public int getSerializedSize() {
 727       int size = memoizedSerializedSize;
 728       if (size != -1) return size;
 729     
 730       size = 0;
 731       if (((bitField0_ & 0x00000001) == 0x00000001)) {
 732         size += com.google.protobuf.CodedOutputStream
 733           .computeInt64Size(1, gold_);
 734       }
 735       if (((bitField0_ & 0x00000002) == 0x00000002)) {
 736         size += com.google.protobuf.CodedOutputStream
 737           .computeInt32Size(2, energy_);
 738       }
 739       size += getUnknownFields().getSerializedSize();
 740       memoizedSerializedSize = size;
 741       return size;
 742     }
 743     
 744     private static final long serialVersionUID = 0L;
 745     @java.lang.Override
 746     protected java.lang.Object writeReplace()
 747         throws java.io.ObjectStreamException {
 748       return super.writeReplace();
 749     }
 750     
 751     public static com.proto.PlayerModule.PBResource parseFrom(
 752         com.google.protobuf.ByteString data)
 753         throws com.google.protobuf.InvalidProtocolBufferException {
 754       return newBuilder().mergeFrom(data).buildParsed();
 755     }
 756     public static com.proto.PlayerModule.PBResource parseFrom(
 757         com.google.protobuf.ByteString data,
 758         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
 759         throws com.google.protobuf.InvalidProtocolBufferException {
 760       return newBuilder().mergeFrom(data, extensionRegistry)
 761                .buildParsed();
 762     }
 763     public static com.proto.PlayerModule.PBResource parseFrom(byte[] data)
 764         throws com.google.protobuf.InvalidProtocolBufferException {
 765       return newBuilder().mergeFrom(data).buildParsed();
 766     }
 767     public static com.proto.PlayerModule.PBResource parseFrom(
 768         byte[] data,
 769         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
 770         throws com.google.protobuf.InvalidProtocolBufferException {
 771       return newBuilder().mergeFrom(data, extensionRegistry)
 772                .buildParsed();
 773     }
 774     public static com.proto.PlayerModule.PBResource parseFrom(java.io.InputStream input)
 775         throws java.io.IOException {
 776       return newBuilder().mergeFrom(input).buildParsed();
 777     }
 778     public static com.proto.PlayerModule.PBResource parseFrom(
 779         java.io.InputStream input,
 780         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
 781         throws java.io.IOException {
 782       return newBuilder().mergeFrom(input, extensionRegistry)
 783                .buildParsed();
 784     }
 785     public static com.proto.PlayerModule.PBResource parseDelimitedFrom(java.io.InputStream input)
 786         throws java.io.IOException {
 787       Builder builder = newBuilder();
 788       if (builder.mergeDelimitedFrom(input)) {
 789         return builder.buildParsed();
 790       } else {
 791         return null;
 792       }
 793     }
 794     public static com.proto.PlayerModule.PBResource parseDelimitedFrom(
 795         java.io.InputStream input,
 796         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
 797         throws java.io.IOException {
 798       Builder builder = newBuilder();
 799       if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
 800         return builder.buildParsed();
 801       } else {
 802         return null;
 803       }
 804     }
 805     public static com.proto.PlayerModule.PBResource parseFrom(
 806         com.google.protobuf.CodedInputStream input)
 807         throws java.io.IOException {
 808       return newBuilder().mergeFrom(input).buildParsed();
 809     }
 810     public static com.proto.PlayerModule.PBResource parseFrom(
 811         com.google.protobuf.CodedInputStream input,
 812         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
 813         throws java.io.IOException {
 814       return newBuilder().mergeFrom(input, extensionRegistry)
 815                .buildParsed();
 816     }
 817     
 818     public static Builder newBuilder() { return Builder.create(); }
 819     public Builder newBuilderForType() { return newBuilder(); }
 820     public static Builder newBuilder(com.proto.PlayerModule.PBResource prototype) {
 821       return newBuilder().mergeFrom(prototype);
 822     }
 823     public Builder toBuilder() { return newBuilder(this); }
 824     
 825     @java.lang.Override
 826     protected Builder newBuilderForType(
 827         com.google.protobuf.GeneratedMessage.BuilderParent parent) {
 828       Builder builder = new Builder(parent);
 829       return builder;
 830     }
 831     public static final class Builder extends
 832         com.google.protobuf.GeneratedMessage.Builder<Builder>
 833        implements com.proto.PlayerModule.PBResourceOrBuilder {
 834       public static final com.google.protobuf.Descriptors.Descriptor
 835           getDescriptor() {
 836         return com.proto.PlayerModule.internal_static_PBResource_descriptor;
 837       }
 838       
 839       protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
 840           internalGetFieldAccessorTable() {
 841         return com.proto.PlayerModule.internal_static_PBResource_fieldAccessorTable;
 842       }
 843       
 844       // Construct using com.proto.PlayerModule.PBResource.newBuilder()
 845       private Builder() {
 846         maybeForceBuilderInitialization();
 847       }
 848       
 849       private Builder(BuilderParent parent) {
 850         super(parent);
 851         maybeForceBuilderInitialization();
 852       }
 853       private void maybeForceBuilderInitialization() {
 854         if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
 855         }
 856       }
 857       private static Builder create() {
 858         return new Builder();
 859       }
 860       
 861       public Builder clear() {
 862         super.clear();
 863         gold_ = 0L;
 864         bitField0_ = (bitField0_ & ~0x00000001);
 865         energy_ = 0;
 866         bitField0_ = (bitField0_ & ~0x00000002);
 867         return this;
 868       }
 869       
 870       public Builder clone() {
 871         return create().mergeFrom(buildPartial());
 872       }
 873       
 874       public com.google.protobuf.Descriptors.Descriptor
 875           getDescriptorForType() {
 876         return com.proto.PlayerModule.PBResource.getDescriptor();
 877       }
 878       
 879       public com.proto.PlayerModule.PBResource getDefaultInstanceForType() {
 880         return com.proto.PlayerModule.PBResource.getDefaultInstance();
 881       }
 882       
 883       public com.proto.PlayerModule.PBResource build() {
 884         com.proto.PlayerModule.PBResource result = buildPartial();
 885         if (!result.isInitialized()) {
 886           throw newUninitializedMessageException(result);
 887         }
 888         return result;
 889       }
 890       
 891       private com.proto.PlayerModule.PBResource buildParsed()
 892           throws com.google.protobuf.InvalidProtocolBufferException {
 893         com.proto.PlayerModule.PBResource result = buildPartial();
 894         if (!result.isInitialized()) {
 895           throw newUninitializedMessageException(
 896             result).asInvalidProtocolBufferException();
 897         }
 898         return result;
 899       }
 900       
 901       public com.proto.PlayerModule.PBResource buildPartial() {
 902         com.proto.PlayerModule.PBResource result = new com.proto.PlayerModule.PBResource(this);
 903         int from_bitField0_ = bitField0_;
 904         int to_bitField0_ = 0;
 905         if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
 906           to_bitField0_ |= 0x00000001;
 907         }
 908         result.gold_ = gold_;
 909         if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
 910           to_bitField0_ |= 0x00000002;
 911         }
 912         result.energy_ = energy_;
 913         result.bitField0_ = to_bitField0_;
 914         onBuilt();
 915         return result;
 916       }
 917       
 918       public Builder mergeFrom(com.google.protobuf.Message other) {
 919         if (other instanceof com.proto.PlayerModule.PBResource) {
 920           return mergeFrom((com.proto.PlayerModule.PBResource)other);
 921         } else {
 922           super.mergeFrom(other);
 923           return this;
 924         }
 925       }
 926       
 927       public Builder mergeFrom(com.proto.PlayerModule.PBResource other) {
 928         if (other == com.proto.PlayerModule.PBResource.getDefaultInstance()) return this;
 929         if (other.hasGold()) {
 930           setGold(other.getGold());
 931         }
 932         if (other.hasEnergy()) {
 933           setEnergy(other.getEnergy());
 934         }
 935         this.mergeUnknownFields(other.getUnknownFields());
 936         return this;
 937       }
 938       
 939       public final boolean isInitialized() {
 940         if (!hasGold()) {
 941           
 942           return false;
 943         }
 944         if (!hasEnergy()) {
 945           
 946           return false;
 947         }
 948         return true;
 949       }
 950       
 951       public Builder mergeFrom(
 952           com.google.protobuf.CodedInputStream input,
 953           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
 954           throws java.io.IOException {
 955         com.google.protobuf.UnknownFieldSet.Builder unknownFields =
 956           com.google.protobuf.UnknownFieldSet.newBuilder(
 957             this.getUnknownFields());
 958         while (true) {
 959           int tag = input.readTag();
 960           switch (tag) {
 961             case 0:
 962               this.setUnknownFields(unknownFields.build());
 963               onChanged();
 964               return this;
 965             default: {
 966               if (!parseUnknownField(input, unknownFields,
 967                                      extensionRegistry, tag)) {
 968                 this.setUnknownFields(unknownFields.build());
 969                 onChanged();
 970                 return this;
 971               }
 972               break;
 973             }
 974             case 8: {
 975               bitField0_ |= 0x00000001;
 976               gold_ = input.readInt64();
 977               break;
 978             }
 979             case 16: {
 980               bitField0_ |= 0x00000002;
 981               energy_ = input.readInt32();
 982               break;
 983             }
 984           }
 985         }
 986       }
 987       
 988       private int bitField0_;
 989       
 990       // required int64 gold = 1;
 991       private long gold_ ;
 992       public boolean hasGold() {
 993         return ((bitField0_ & 0x00000001) == 0x00000001);
 994       }
 995       public long getGold() {
 996         return gold_;
 997       }
 998       public Builder setGold(long value) {
 999         bitField0_ |= 0x00000001;
1000         gold_ = value;
1001         onChanged();
1002         return this;
1003       }
1004       public Builder clearGold() {
1005         bitField0_ = (bitField0_ & ~0x00000001);
1006         gold_ = 0L;
1007         onChanged();
1008         return this;
1009       }
1010       
1011       // required int32 energy = 2;
1012       private int energy_ ;
1013       public boolean hasEnergy() {
1014         return ((bitField0_ & 0x00000002) == 0x00000002);
1015       }
1016       public int getEnergy() {
1017         return energy_;
1018       }
1019       public Builder setEnergy(int value) {
1020         bitField0_ |= 0x00000002;
1021         energy_ = value;
1022         onChanged();
1023         return this;
1024       }
1025       public Builder clearEnergy() {
1026         bitField0_ = (bitField0_ & ~0x00000002);
1027         energy_ = 0;
1028         onChanged();
1029         return this;
1030       }
1031       
1032       // @@protoc_insertion_point(builder_scope:PBResource)
1033     }
1034     
1035     static {
1036       defaultInstance = new PBResource(true);
1037       defaultInstance.initFields();
1038     }
1039     
1040     // @@protoc_insertion_point(class_scope:PBResource)
1041   }
1042   
1043   private static com.google.protobuf.Descriptors.Descriptor
1044     internal_static_PBPlayer_descriptor;
1045   private static
1046     com.google.protobuf.GeneratedMessage.FieldAccessorTable
1047       internal_static_PBPlayer_fieldAccessorTable;
1048   private static com.google.protobuf.Descriptors.Descriptor
1049     internal_static_PBResource_descriptor;
1050   private static
1051     com.google.protobuf.GeneratedMessage.FieldAccessorTable
1052       internal_static_PBResource_fieldAccessorTable;
1053   
1054   public static com.google.protobuf.Descriptors.FileDescriptor
1055       getDescriptor() {
1056     return descriptor;
1057   }
1058   private static com.google.protobuf.Descriptors.FileDescriptor
1059       descriptor;
1060   static {
1061     java.lang.String[] descriptorData = {
1062       "n22proto/player.proto"Gn10PBPlayer2220n10play" +
1063       "erId3001 02(032213n03age3002 02(052214n04name3003 02(t2216n" +
1064       "06skills3004 03(05"*nnPBResource2214n04gold3001 02(" +
1065       "032216n06energy3002 02(05B31ntcom.protoB14PlayerMo" +
1066       "dule"
1067     };
1068     com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
1069       new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
1070         public com.google.protobuf.ExtensionRegistry assignDescriptors(
1071             com.google.protobuf.Descriptors.FileDescriptor root) {
1072           descriptor = root;
1073           internal_static_PBPlayer_descriptor =
1074             getDescriptor().getMessageTypes().get(0);
1075           internal_static_PBPlayer_fieldAccessorTable = new
1076             com.google.protobuf.GeneratedMessage.FieldAccessorTable(
1077               internal_static_PBPlayer_descriptor,
1078               new java.lang.String[] { "PlayerId", "Age", "Name", "Skills", },
1079               com.proto.PlayerModule.PBPlayer.class,
1080               com.proto.PlayerModule.PBPlayer.Builder.class);
1081           internal_static_PBResource_descriptor =
1082             getDescriptor().getMessageTypes().get(1);
1083           internal_static_PBResource_fieldAccessorTable = new
1084             com.google.protobuf.GeneratedMessage.FieldAccessorTable(
1085               internal_static_PBResource_descriptor,
1086               new java.lang.String[] { "Gold", "Energy", },
1087               com.proto.PlayerModule.PBResource.class,
1088               com.proto.PlayerModule.PBResource.Builder.class);
1089           return null;
1090         }
1091       };
1092     com.google.protobuf.Descriptors.FileDescriptor
1093       .internalBuildGeneratedFileFrom(descriptorData,
1094         new com.google.protobuf.Descriptors.FileDescriptor[] {
1095         }, assigner);
1096   }
1097   
1098   // @@protoc_insertion_point(outer_class_scope)
1099 }

PB序列化

 1         //获取一个PBPlayer的构造器
 2         Builder builder = PlayerModule.PBPlayer.newBuilder();
 3         //设置数据
 4         builder.setPlayerId(101).setAge(20).setName("neil").addSkills(1001);
 5         //构造出对象
 6         PBPlayer player = builder.build();
 7         //序列化成字节数组
 8         byte[] byteArray = player.toByteArray();
 9         System.out.println(Arrays.toString(byteArray));
10         return byteArray;

运行结果, 一串非常短的byte数组, 远远比json, xml, java序列化要短.

[8, 101, 16, 20, 26, 4, 110, 101, 105, 108, 32, -23, 7]

PB反序列化

1     public static void toPlayer(byte[] bs) throws Exception{
2          PBPlayer player = PlayerModule.PBPlayer.parseFrom(bs);
3          System.out.println("playerId:" + player.getPlayerId());
4          System.out.println("age:" + player.getAge());
5          System.out.println("name:" + player.getName());
6          System.out.println("skills:" + (Arrays.toString(player.getSkillsList().toArray())));
7     }

运行结果

playerId:101 age:20 name:neil skills:[1001]

Java序列化

定义player pojo.

1     private long playerId;
2     private int age;
3     private String name;
4     private List<Integer> skills = new ArrayList<>();
 1         Player player = new Player(101, 20, "neil");
 2         player.getSkills().add(1001);
 3 
 4         ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
 5         ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
 6 
 7         //写入对象
 8         objectOutputStream.writeObject(player);
 9 
10         //获取 字节数组
11         byte[] byteArray = byteArrayOutputStream.toByteArray();
12         System.out.println(Arrays.toString(byteArray));
13         return byteArray;

运行结果, 非常长的一个byte数组

[-84, -19, 0, 5, 115, 114, 0, 15, 99, 111, 109, 46, 106, 97, 118, 97, 46, 80, 108, 97, 121, 101, 114, -73, 43, 28, 39, -119, -86, -125, -3, 2, 0, 4, 73, 0, 3, 97, 103, 101, 74, 0, 8, 112, 108, 97, 121, 101, 114, 73, 100, 76, 0, 4, 110, 97, 109, 101, 116, 0, 18, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, 103, 59, 76, 0, 6, 115, 107, 105, 108, 108, 115, 116, 0, 16, 76, 106, 97, 118, 97, 47, 117, 116, 105, 108, 47, 76, 105, 115, 116, 59, 120, 112, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 101, 116, 0, 4, 110, 101, 105, 108, 115, 114, 0, 19, 106, 97, 118, 97, 46, 117, 116, 105, 108, 46, 65, 114, 114, 97, 121, 76, 105, 115, 116, 120, -127, -46, 29, -103, -57, 97, -99, 3, 0, 1, 73, 0, 4, 115, 105, 122, 101, 120, 112, 0, 0, 0, 1, 119, 4, 0, 0, 0, 1, 115, 114, 0, 17, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 73, 110, 116, 101, 103, 101, 114, 18, -30, -96, -92, -9, -127, -121, 56, 2, 0, 1, 73, 0, 5, 118, 97, 108, 117, 101, 120, 114, 0, 16, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 78, 117, 109, 98, 101, 114, -122, -84, -107, 29, 11, -108, -32, -117, 2, 0, 0, 120, 112, 0, 0, 3, -23, 120]

Java反序列化

1         ObjectInputStream inputStream = new ObjectInputStream(new ByteArrayInputStream(bs));
2         Player player = (Player)inputStream.readObject();
3         
4         //打印
5          System.out.println("playerId:" + player.getPlayerId());
6          System.out.println("age:" + player.getAge());
7          System.out.println("name:" + player.getName());
8          System.out.println("skills:" + (Arrays.toString(player.getSkills().toArray())));

运行结果

playerId:101 age:20 name:neil skills:[1001]

对比

经过上面运行结果的对比可以看出来, PB是一个非常高效的序列化协议.

相对于Java这种数据类型固定长度的序列化(int 4字节, long 8字节), PB提供了可伸缩性的数据类型(int 1-5字节).

当数据比较小的时候int只占用1个字节, 而大部分场景下, 数据都是很小的, 不然jdk本身也不会缓存 -127~128了.