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_ =

