protobuf原理以及实例(Varint编码)
发布人:shili8
发布时间:2025-01-23 01:07
阅读次数:0
**Protobuf 原理与实例**
Protocol Buffers(protobuf)是一种轻量级的数据序列化格式,由谷歌开发。它提供了一种高效、易用且可扩展的方式来序列化和反序列化数据。protobuf 的原理是通过定义一个 `.proto` 文件来描述数据结构,然后使用 protobuf 编译器生成相应语言的代码。
**Varint 编码**
protobuf 使用 Varint(Variable-length integer)编码来压缩整数值。这是一种高效的方式来存储小整数值。Varint 编码使用以下规则:
*0 到63 的整数值直接写入到字节流中。
*64 到16383 的整数值写入一个字节,前面有一个标志位(1),后面跟着实际的值。
*16384 到2097151 的整数值写入两个字节,前面有一个标志位(1),后面跟着实际的值。
*2097152 到268435455 的整数值写入三个字节,前面有一个标志位(1),后面跟着实际的值。
**protobuf 原理**
protobuf 的原理是通过定义一个 `.proto` 文件来描述数据结构,然后使用 protobuf 编译器生成相应语言的代码。`.proto` 文件中可以定义各种类型的字段,如整数、字符串、枚举等。
下面是一个简单的例子:
protosyntax = "proto3"; message Person { int32 id =1; string name =2; }
在这个例子中,我们定义了一个 `Person` 消息,它包含两个字段:`id` 和 `name`。`id` 是一个整数类型,`name` 是一个字符串类型。
**protobuf 编译器**
protobuf 编译器可以将 `.proto` 文件编译成相应语言的代码,如 Java、Python 等。在这个例子中,我们使用 protobuf 编译器生成 Java代码:
bashprotoc --java_out=. person.proto
这会在当前目录下生成一个 `Person.java` 文件。
**protobuf 实例**
下面是一个简单的例子,演示如何使用 protobuf 序列化和反序列化数据:
javaimport com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.Message; public class Person { private int id; private String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } public class PersonProto implements Message { private static final int ID_FIELD_NUMBER =1; private static final int NAME_FIELD_NUMBER =2; private int id_; private String name_; public static PersonProto parseFrom(com.google.protobuf.ByteString data) throws InvalidProtocolBufferException { return new PersonProto(data); } public static PersonProto parseFrom(byte[] data) throws InvalidProtocolBufferException { return parseFrom((com.google.protobuf.ByteString) com.google.protobuf.ByteString.wrap(data)); } public static PersonProto parseFrom(com.google.protobuf.ByteString data, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { return new PersonProto(data, extensionRegistry); } public static PersonProto parseFrom(byte[] data, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { return parseFrom((com.google.protobuf.ByteString) com.google.protobuf.ByteString.wrap(data), extensionRegistry); } public static PersonProto parseFrom(com.google.protobuf.ByteString data, CodedInputStream input, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { return new PersonProto(data, input, extensionRegistry); } public static PersonProto parseFrom(CodedInputStream input) throws InvalidProtocolBufferException { return new PersonProto(input); } public static PersonProto parseFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { return new PersonProto(input, extensionRegistry); } private PersonProto(com.google.protobuf.ByteString data) throws InvalidProtocolBufferException { this(data, null, null); } private PersonProto(com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { this(data, extensionRegistry, (com.google.protobuf.CodedInputStream) null); } private PersonProto(com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry, com.google.protobuf.CodedInputStream input) throws InvalidProtocolBufferException { initFields(); int tag =0; while (!input.isAtEnd()) { int wire_tag = input.readTag(); switch (wire_tag >>3) { case0: throw new InvalidProtocolBufferException("Invalid wire type."); case1: // varint switch (wire_tag &7) { case0: if (ID_FIELD_NUMBER == tag) { id_ = input.readInt32(); break; } tag++; continue; case1: if (NAME_FIELD_NUMBER == tag) { name_ = input.readString(); break; } tag++; continue; } default: // length-delimited switch (wire_tag &7) { case0: if (ID_FIELD_NUMBER == tag) { id_ = input.readInt32(); break; } tag++; continue; case1: if (NAME_FIELD_NUMBER == tag) { name_ = input.readString(); break; } tag++; continue; } } } makeExtensionsImmutable(); } private PersonProto(com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry, com.google.protobuf.CodedInputStream input) throws InvalidProtocolBufferException { initFields(); int tag =0; while (!input.isAtEnd()) { int wire_tag = input.readTag(); switch (wire_tag >>3) { case0: throw new InvalidProtocolBufferException("Invalid wire type."); case1: // varint switch (wire_tag &7) { case0: if (ID_FIELD_NUMBER == tag) { id_ = input.readInt32(); break; } tag++; continue; case1: if (NAME_FIELD_NUMBER == tag) { name_ = input.readString(); break; } tag++; continue; } default: // length-delimited switch (wire_tag &7) { case0: if (ID_FIELD_NUMBER == tag) { id_ = input.readInt32(); break; } tag++; continue; case1: if (NAME_FIELD_NUMBER == tag) { name_ = input.readString(); break; } tag++; continue; } } } makeExtensionsImmutable(); } private PersonProto(com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { initFields(); int tag =0; while (!input.isAtEnd()) { int wire_tag = input.readTag(); switch (wire_tag >>3) { case0: throw new InvalidProtocolBufferException("Invalid wire type."); case1: // varint switch (wire_tag &7) { case0: if (ID_FIELD_NUMBER == tag) { id_ = input.readInt32(); break; } tag++; continue; case1: if (NAME_FIELD_NUMBER == tag) { name_ = input.readString(); break; } tag++; continue; } default: // length-delimited switch (wire_tag &7) { case0: if (ID_FIELD_NUMBER == tag) { id_ = input.readInt32(); break; } tag++; continue; case1: if (NAME_FIELD_NUMBER == tag) { name_ = input.readString(); break; } tag++; continue; } } } makeExtensionsImmutable(); } private PersonProto(com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry, com.google.protobuf.CodedInputStream input) throws InvalidProtocolBufferException { initFields(); int tag =0; while (!input.isAtEnd()) { int wire_tag = input.readTag(); switch (wire_tag >>3) { case0: throw new InvalidProtocolBufferException("Invalid wire type."); case1: // varint switch (wire_tag &7) { case0: if (ID_FIELD_NUMBER == tag) { id_ = input.readInt32(); break; } tag++; continue; case1: if (NAME_FIELD_NUMBER == tag) { name_ = input.readString(); break; } tag++; continue; } default: // length-delimited switch (wire_tag &7) { case0: if (ID_FIELD_NUMBER == tag) { id_ =