Protobuf简介-创新互联

protobuf(protocol buffer) 是谷歌内部的混合语言数据标准。通过将结构化的数据进行序列化(串行化),用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。通常说的protobuf包括以下三点:

为景谷等地区用户提供了全套网页设计制作服务,及景谷网站建设行业解决方案。主营业务为网站建设、做网站、景谷网站设计,以传统方式定制建设网站,并提供域名空间备案等一条龙服务,秉承以专业、用心的态度为用户提供真诚的服务。我们深信只要达到每一位用户的要求,就会得到认可,从而选择与我们长期合作。这样,我们也可以走得更远!
  • 是一种二进制数据交换格式。支持不同与语言例如C++、java中定义的存储类的内容与二进制序列串相互转换,主要用于数据传输或保存。
  • 定义了一种源文件,扩展名为.proto.使用此文件,可以定义存储类的内容。
  • 可以使用编译器将.proto编译成.cc 或.java,使之成为一个可以在C++或java等工程中直接使用的类。
定义Proto文件

messageprotobuf中定义一个消息类型是通过关键字message字段指定的,这个关键字类似于C++/Java中的class关键字。使用protobuf编译器将proto编译成C++代码之后,每个message都会生成一个名字与之对应的C++类,该类公开继承自google::protobuf::Message

创建turorial.person.proto 文件,文件内容如下:

// FileName: tutorial.person.proto

// 通常文件名建议命名格式为 包名.消息名.proto

// 表示正在使用proto2命令

syntax = "proto2";

//包声明,tutorial 也可以声明为二级类型。

//例如a.b,表示a类别下b子类别

package tutorial;

//编译器将生成一个名为person的类

//类的字段信息包括姓名name,编号id,邮箱email,

//以及电话号码phones

message Person {

required string name = 1;  // (位置1)

required int32 id = 2; 

optional string email = 3;  // (位置2)

enum PhoneType {  //电话类型枚举值

MOBILE = 0;  //手机号 

HOME = 1;    //家庭联系电话

WORK = 2;    //工作联系电话

}

//电话号码phone消息体

//组成包括号码number、电话类型 type

message PhoneNumber {

required string number = 1;   

optional PhoneType type =

2 [default = HOME]; // (位置3)

repeated PhoneNumber phones = 4; // (位置4)

}

// 通讯录消息体,包括一个Person类的people

message AddressBook {

repeated Person people = 1;

}

字段解释:

包声明

proto文件以package声明开头,这有助于防止不同项目之间命名冲突。在C++中,以package声明的文件内容生成的类将放在与包名匹配的namespace中,上面的.proto文件中所有的声明都属于tutorial

标识符:

protobuf协议的标识符为message或enum,如示例中的Person和PhoneType。message标识一条消息,enum标识一个枚举类型。使用protobuf编译器将协议文件编译后,message和enum都会生成一个类

字段规则

·  repeated: 消息体中可重复字段,重复的值的顺序会被保留(例如位置3)。其中,proto3默认使用packed方式存储,这样编码方式比较节省内存。

标识号

标识号:在消息体的定义中,每个字段都必须要有一个唯一的标识号,标识号是[0,2^29-1]范围内的一个整数。以Person为例,name=1,id=2, email=3, phones=4 中的1-4就是标识号。

数据定义

许多标准的简单数据类型都可以用作message字段类型,包括bool,int32,float,doublestring。还可以使用其他message类型作为字段类型在消息体中添加更多结构。在上面的示例中,Person包含PhoneNumber message, 而AddressBook包含Person message。甚至可以定义嵌套在其他message中的message类型。例如,上面的PhoneNumber定义在Person

在java中使用protobuf的简单示例

以下是示例中用到的proto文件teacher.proto:

syntax = "proto3";

package space;

message course{

// 课程名称

string name = 1;

// 课程分数

int32 score = 2;

}

message student{

// 学生名称

string name = 1;

// 学生年龄

int32 age = 2;

// 学生所修课程,可能是多门,是一组数组

repeated course course = 3;

}

从Release Protocol Buffers v3.5.1 · protocolbuffers/protobuf · GitHub 下载protoc工具,此工具可以根据proto文件生成java类。

下载完成后,解压缩该文件。

打开cmd命令窗口,跳转至解压缩路径:

执行以下命令:

protoc.exe --java_out=src/main/java/ teacher.proto

执行此命令前,需要在新建文件夹目录src/main/java

执行成功后,可以看到在src/main/java 下生成的java类文件Teacher.java。

新建一个maven工程,并导入以下pom依赖

com.google.protobuf

protobuf-java

3.21.9

com.google.protobuf

protobuf-java-util

3.21.9

  

io.grpc

grpc-all

1.11.0

  

kr.motd.maven

os-maven-plugin

1.5.0.Final

org.xolstice.maven.plugins

protobuf-maven-plugin

0.5.0

    

         com.google.protobuf:protoc:3.1.0:exe:${os.detected.classifier}

    

    grpc-java

    

         io.grpc:protoc-gen-grpc-java:1.11.0:exe:${os.detected.classifier}

    

    

        

            compile

            compile-custom

        

    

将Teacher.java 添加至该工程。新建一个测试类TestMyProtobuf.java 进行测试。代码如下:

import com.google.protobuf.InvalidProtocolBufferException;

import com.google.protobuf.util.JsonFormat;

import space.Teacher;

import java.util.Arrays;

public class TestMyProtobuf {

public static void main(String[] args) {

// 生成课程1对象

Teacher.course.Builder courseBuilder1 = Teacher.course.newBuilder();

courseBuilder1.setName("Java");

courseBuilder1.setScore(99);

Teacher.course course1 = courseBuilder1.build();

// 生成课程2对象

Teacher.course.Builder courseBuilder2 = Teacher.course.newBuilder();

courseBuilder2.setName("Python");

courseBuilder2.setScore(98);

Teacher.course course2 = courseBuilder2.build();

// 生成学生对象

Teacher.student.Builder studentBuilder = Teacher.student.newBuilder();

studentBuilder.setName("Lucy");

studentBuilder.setAge(23);

studentBuilder.addCourse(0,course1);

studentBuilder.addCourse(1,course2);

Teacher.student student = studentBuilder.build();

// proto对象

System.out.println("The student object is: \n" + student);

// 序列化

byte[] studentByte = student.toByteArray();

System.out.println("The student after encode is:\n" + Arrays.toString(studentByte));

try {

// 反序列化

Teacher.student newStudent = Teacher.student.parseFrom(studentByte);

System.out.println("The student after decode is:\n" + newStudent);

// 转换json

System.out.println("The student json format is:\n" + JsonFormat.printer().print(student));

} catch (InvalidProtocolBufferException e) {

e.printStackTrace();

}

}

}

测试结果如下:

The student object is:

name: "Lucy"

age: 23

course {

name: "Java"

score: 99

}

course {

name: "Python"

score: 98

}

The student after encode is:

[10, 4, 76, 117, 99, 121, 16, 23, 26, 8, 10, 4, 74, 97, 118, 97, 16, 99, 26, 10, 10, 6, 80, 121, 116, 104, 111, 110, 16, 98]

The student after decode is:

name: "Lucy"

age: 23

course {

name: "Java"

score: 99

}

course {

name: "Python"

score: 98

}

The student json format is:

{

"name": "Lucy",

"age": 23,

"course": [{

"name": "Java",

"score": 99

}, {

"name": "Python",

"score": 98

}]

}

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


本文题目:Protobuf简介-创新互联
浏览地址:http://myzitong.com/article/coihpi.html