上一篇,介紹了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是累加的