相关资料
代码地址: https://github.com/viakiba/viakiba/tree/master/proto_demo/helloworld 资料来源: https://developers.google.com/protocol-buffers/docs/proto3#updating https://www.tizi365.com/archives/367.html
进入 下载 页面,如图选择对应的操作系统的文件进行下载。
上方的是可以自己根据需要自行编译。
我下载的是 protoc-3.12.3-win64.zip 解压到指定的文件夹 如图:
并且把 bin 文件路径添加到 Path 环境变量之中。
验证安装 cmd 输入 protoc 输出有提示即安装成功。
/* 多行注释 */ syntax = "proto3"; //1. 双斜杠后面可以加注释 2. 设置语法 可选 proto3 、 proto2 package hello.world.example;// package 声明有助于防止不同项目之间的命名冲突。 message Person { string name = 1; //定义一个字段 name 属性 }
文件位置如图
执行命令如下
protoc -I=C://Users//89264//Desktop//helloworld --java_out=C://Users//89264//Desktop//helloworld//JavaMessageBuild C://Users//89264//Desktop//helloworld//message//hello.proto # -I 指定绝对路径 # --java_out 指定输出 java 消息的文件位置 # --python_out 指定输出 python 消息的文件位置 # 后面跟上 刚刚写好的 proto 的文件
结果如下图
创建一个 maven 工程,根文件夹选择 C:/Users/89264/Desktop/helloworld .
注意标记 JavaMessageBuild 为 sourceRoot 如图所示
引入依赖:
<dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java</artifactId> <version>3.12.2</version> </dependency>
// write String name = "hello_world"; Hello.Person.Builder builder = Hello.Person.newBuilder(); builder.setName(name); Hello.Person build = builder.build(); // Person 继承 com.google.protobuf.GeneratedMessageV3 抽象类 byte[] bytes = build.toByteArray(); System.out.println(Base64.getEncoder().encodeToString(bytes)); // read Hello.Person builderreader = Hello.Person.parseFrom(bytes); String nameReader = builderreader.getName(); System.out.println(nameReader);
https://developers.google.com/protocol-buffers/docs/proto3 这里看到了一个翻译贴 https://www.tizi365.com/archives/371.html 和官网查不多 直接看就好了 不多翻译了
我们上面写的proto文件中,name属性后面跟的有一个 1 ,此处的 的 1 叫做标识号. 值得注意的是,这些标识号是用来在消息的二进制格式中识别各个字段的,一旦开始使用就不能够再改变,每个消息内唯一即可,不同的消息定义可以拥有相同的标识号。
注意:[1,15]之内的标识号在编码的时候会占用一个字节。[16,2047]之内的标识号则占用2个字节。所以应该为那些频繁出现的消息元素保留 [1,15]之内的标识号。切记:要为将来有可能添加的、频繁出现的字段预留一些标识号。
message Hello { reserved 2, 15, 9 to 11; // 保留2,15,9到11这些标识号 reserved "foo", "bar"; // 保留foo bar 这些字段名称 但是 不可同时使用保留 字段名称与标识号 }
我们上面写的proto文件中,package 指定为 hello.world.example 则对应 文件夹 hello/world/example . 同时在声明package参数时,可以指定 java_package 与 java_outer_classname. 前者单独为java定义包名字。后者单独为java定义,protobuf编译器生成的类名。
--cpp_out=OUT_DIR 指定代码生成目录,生成 C++ 代码 --csharp_out=OUT_DIR 指定代码生成目录,生成 C# 代码 --java_out=OUT_DIR 指定代码生成目录,生成 java 代码 --js_out=OUT_DIR 指定代码生成目录,生成 javascript 代码 --objc_out=OUT_DIR 指定代码生成目录,生成 Objective C 代码 --php_out=OUT_DIR 指定代码生成目录,生成 php 代码 --python_out=OUT_DIR 指定代码生成目录,生成 python 代码 --ruby_out=OUT_DIR 指定代码生成目录,生成 ruby 代码 --go_out=OUT_DIR 指定代码生成目录,生成 go 代码
部分语言 需要安装插件,例如 goo语言:
安装go语言的protoc编译器插件 go get -u github.com/golang/protobuf/protoc-gen-go 注意: 安装go语言插件后,需要将 $GOPATH/bin 路径加入到PATH环境变量中。
https://developers.google.com/protocol-buffers/docs/proto3#scalar
当解析消息时,如果编码的消息不包含特定的单一元素,则解析的对象中的相应字段被设置为该字段的默认值。 这些默认值是特定于类型的:
请注意,对于标量消息字段,一旦解析了消息,就无法判断字段是显式设置为默认值(例如,布尔值是否设置为false),还是根本没有设置:在定义消息类型时,您应该牢记这一点。 例如,如果您不希望某些行为在默认情况下也发生,则不要使用布尔值在设置为false时打开该行为。 还要注意,如果将标量消息字段设置为其默认值,则该值将不会在网络上序列化。 有关默认如何在生成的代码中工作的更多详细信息,请参见所选语言的生成代码指南。
https://developers.google.com/protocol-buffers/docs/proto3#enum https://www.tizi365.com/archives/376.html
注意
枚举类需要一个 0 值的枚举字段.原因有两个: 1. 作为默认值 2. 兼容proto2 .
不同的枚举常量分配相同的值来定义别名 设置 option allow_alias = true
message MyMessage1 { enum EnumAllowingAlias { option allow_alias = true; UNKNOWN = 0; STARTED = 1; RUNNING = 1; } } message MyMessage2 { enum EnumNotAllowingAlias { UNKNOWN = 0; STARTED = 1; // RUNNING = 1; // Uncommenting this line will cause a compile error inside Google and a warning message outside. } }
message Msg { // 只要使用repeated标记类型定义,就表示数组类型。int32 可以替换为任何类型 repeated int32 arrays = 1; }
https://developers.google.com/protocol-buffers/docs/proto3#maps https://www.tizi365.com/archives/383.html
注意
key_type 只能是 数字 or 字符串 映射按键排序。 数字键按数字排序。 值的迭代排序未定义,因此您不能依赖于项目按特定顺序排列。 map字段不能同时使用repeated。
未知类型是指数据的格式符合Protobuf的定义,但是数据中的某个/某些字段解析器无法识别的字段类型。 一般发生在proto文件有变化,新旧数据不一致的情况导致。 proto3最开始对于不能识别的数据就丢弃掉了,但是自3.5 版本后重新引入了未知字段,以匹配proto2的行为。