上一篇,介绍了proto文件,以及用idea的工具编译了proto文件。固然,咱们也能够直接用protoc命令来编译。java
protoc -I=SRC_DIR --java_out=DST_DIR SRC_DIR/hello.proto
F:\soft\protoc-3.10.1-win64\bin
的目录(以本身的环境为准),要么配置在系统环境变量path里。-I=IMPORT_PATH
写法同--proto_path=IMPORT_PATH
,用来指定proto文件目录,--java_out=
指定生成的java文件存放的目录,java的类名同proto文件名,可是若是Message的名称和proto名称同样,好比上一篇的简单例子,proto文件名是Person.proto,Message也是Person,那类名就是PersonOutClass。若是是proto文件名是foo_bar.proto,那类名就是FooBar。这边要注意的是,文件夹是要存在的,protoc不会帮咱们建立。proto文件segmentfault
syntax = "proto3"; package ch13; option java_package = "com.example.ch13"; option java_outer_classname = "AddressBookProtos"; message Person { string name = 1; int32 id = 2; string email = 3; enum PhoneType { MOBILE = 0; HOME = 1; WORK = 2; } message PhoneNumber { string number = 1; PhoneType type = 2 ; } repeated PhoneNumber phones = 4; } message AddressBook { repeated Person person = 1; }
生成java文件AddressBookProtos.java后,咱们看看java类里有哪些内容。ide
PersonOrBuilder继承了com.google.protobuf.MessageOrBuilder
,咱们看看这个接口的几个方法,都是对应咱们在proto文件中定义的字段,很像咱们的javaBean,可是没有set方法,有get方法。
对于Repeated字段,还提供了其余的方法,好比经过索引查找、获取个数等。工具
// 对应着name java.lang.String getName(); com.google.protobuf.ByteString getNameBytes(); // 对应着id int getId(); // 对应着email java.lang.String getEmail(); com.google.protobuf.ByteString getEmailBytes(); // 对应着phones java.util.List<com.example.ch13.AddressBookProtos.Person.PhoneNumber> getPhonesList(); com.example.ch13.AddressBookProtos.Person.PhoneNumber getPhones(int index); int getPhonesCount(); java.util.List<? extends com.example.ch13.AddressBookProtos.Person.PhoneNumberOrBuilder> getPhonesOrBuilderList(); com.example.ch13.AddressBookProtos.Person.PhoneNumberOrBuilder getPhonesOrBuilder(int index);
Person继承了com.google.protobuf.GeneratedMessageV3,还实现了上面的PersonOrBuilder接口。
Person类中定义了一个枚举PhoneType:
Message中嵌套了PhoneNumber,因此Person中包含了PhoneNumberOrBuilder和PhoneNumber,这两个结构同PersonOrBuilder和Person:
Person类中还包含了重要的Builder,这个后面在详细说。
除了上面几个枚举、接口、类,还包含了几个方法:getDefaultInstance
:返回Person的单例。等同于Person.newBuilder().build()
ui
public static com.example.ch13.AddressBookProtos.Person getDefaultInstance() { return DEFAULT_INSTANCE; }
parseFrom(...)
:解析给定的数据源,转成Message对象的Person。newBuilder
:建立一个buildgoogle
Builder继承了com.google.protobuf.GeneratedMessageV3.Builder<Builder>
,还实现了PersonOrBuilder接口。
主要有构建类,对字段的set、get、clear等操做。idea
先获取Builder,而后对各个实例进行set或者add操做,最后build返回一个AddressBook,经过AddressBook的writeTo方法,把序列号的值写入文件。
AddPersonspa
class AddPerson { public static void main(String[] args) throws Exception { AddressBook.Builder builder =AddressBook.newBuilder().addPerson(Person.newBuilder().setName("aa") .setId(1) .setEmail("123@qq.com") .addPhones(Person.PhoneNumber.newBuilder() .setNumber("111") .setType(Person.PhoneType.HOME)) .addPhones(Person.PhoneNumber.newBuilder() .setNumber("222") .setType(Person.PhoneType.MOBILE))).addPerson(Person.newBuilder().setName("bb") .setId(2) .setEmail("456@qq.com") .addPhones(Person.PhoneNumber.newBuilder() .setNumber("333") .setType(Person.PhoneType.HOME)) .addPhones(Person.PhoneNumber.newBuilder() .setNumber("444") .setType(Person.PhoneType.MOBILE))); AddressBook addressBook = builder.build(); PersonList.Print(addressBook); addressBook.writeTo(new FileOutputStream("f:\\1.txt")); } }
PersonList3d
class PersonList { static void Print(AddressBook addressBook) { for (Person person: addressBook.getPersonList()) { System.out.println("Person ID: " + person.getId()); System.out.println(" Name: " + person.getName()); System.out.println(" E-mail address: " + person.getEmail()); for (Person.PhoneNumber phoneNumber : person.getPhonesList()) { switch (phoneNumber.getType()) { case MOBILE: System.out.print(" Mobile phone #: "); break; case HOME: System.out.print(" Home phone #: "); break; case WORK: System.out.print(" Work phone #: "); break; } System.out.println(phoneNumber.getNumber()); } } } }
运行结果:code
ListPeople,经过parseFrom读取
class ListPeople { public static void main(String[] args) throws Exception { AddressBook addressBook = AddressBook.parseFrom(new FileInputStream("f:\\1.txt")); PersonList.Print(addressBook); } }
运行结果同上。
public class MergePerson { public static void main(String[] args) { Person person1 =Person.newBuilder().setId(1).addPhones(Person.PhoneNumber.newBuilder().setNumber("111").setType(Person.PhoneType.MOBILE)).build(); Person person2 =Person.newBuilder().setId(2).addPhones(Person.PhoneNumber.newBuilder().setNumber("222").setType(Person.PhoneType.WORK)).build(); person1 = person1.toBuilder().mergeFrom(person2).build(); System.out.println("Person ID: " + person1.getId()); for (Person.PhoneNumber phoneNumber : person1.getPhonesList()) { switch (phoneNumber.getType()) { case MOBILE: System.out.print(" Mobile phone #: "); break; case HOME: System.out.print(" Home phone #: "); break; case WORK: System.out.print(" Work phone #: "); break; } System.out.println(phoneNumber.getNumber()); } } }
运行结果以下:能够看出id被后面的覆盖了,而PhoneNumber是累加的