ImageVerifierCode 换一换
格式:DOCX , 页数:14 ,大小:161.23KB ,
资源ID:19741520      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/19741520.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(protobuf入门Word格式文档下载.docx)为本站会员(b****5)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

protobuf入门Word格式文档下载.docx

1、Protocol Buffers可以灵活,高效且自动化的解决该问题,只需要:1.创建一个.proto 文件,描述希望数据存储结构2.使用PB compiler 创建一个类,该类可以高效的,以二进制方式自动编码和解析PB数据该生成类提供组成PB数据字段的getter和setter方法,甚至考虑了如何高效的读写PB数据。更厉害的是,PB友好的支持字段拓展,拓展后的代码,依然能够正确的读取原来格式编码的数据。3. 定义协议格式首先需要创建一个.proto文件。非常简单,每一个需要序列化的数据结构,编码一个PB message,然后为message中的字段指明一个名字和类型即可。该“通讯簿”的.pro

2、to 文件addressbook.proto定义如下:package tutorial;option java_package = com.example.tutorial;option java_outer_classname = AddressBookProtosmessage Person required string name = 1; required int32 id = 2; optional string email = 3; enum PhoneType MOBILE = 0; HOME = 1; WORK = 2; message PhoneNumber required

3、 string number = 1; optional PhoneType type = 2 default = HOME; repeated PhoneNumber phone = 4;message AddressBook repeated Person person = 1;可以看到,语法非常类似Java或者C+,接下来,我们一条一条来过一遍每句话的含义:.proto文件以一个package声明开始。该声明有助于避免不同项目建设的命名冲突。Java版的PB,在没有指明java_package的情况下,生成的类默认的package即为此package。这里我们生命的java_packag

4、e,所以最终生成的类会位于com.example.tutorial package下。这里需要强调一下,即使指明了java_package,我们建议依旧定义.proto文件的package。在package声明之后,紧接着是专门为java指定的两个选项:java_package 以及 java_outer_classname。java_package我们已经说过,不再赘述。java_outer_classname为生成类的名字,该类包含了所有在.proto中定义的类。如果该选项不显式指明的话,会按照驼峰规则,将.proto文件的名字作为该类名。例如“addressbook.proto”将会是“

5、Addressbook”,“address_book.proto”即为“AddressBook”java指定选项后边,即为message定义。每个message是一个包含了一系列指明了类型的字段的集合。这里的字段类型包含大多数的标准简单数据类型,包括bool,int32,float,double以及string。Message中也可以定义嵌套的message,例如“Person” message 包含“PhoneNumber” message。也可以将已定义的message作为新的数据类型,例如上例中,PhoneNumber类型在Person内部定义,但他是phone的type。在需要一个字段

6、包含预先定义的一个列表的时候,也可以定义枚举类型,例如“PhoneType”。我们注意到, 每一个message中的字段,都有“=1”,“=2”这样的标记,这可不是初始化赋值,该值是message中,该字段的唯一标示符,在二进制编码时候会用到。数字115的表示需求少于一个字节,所以在编码的时候,有这样一个优化,你可以用115标记最常使用或者重复字段元素(repeated elements)。用16或者更大的数字来标记不太常用的可选元素。再重复字段中,每一个元素都需重复编码标签数字,所以,该优化对重复字段最佳(repeat fileds)。message的没一个字段,都要用如下的三个修饰符(mo

7、difier)来声明:1.required:必须赋值,不能为空,否则该条message会被认为是“uninitialized”。build一个“uninitialized” message会抛出一个RuntimeException异常,解析一条“uninitialized” message会抛出一条IOException异常。除此之外,“required”字段跟“optional”字段并无差别。2.optional:字段可以赋值,也可以不赋值。假如没有赋值的话,会被赋上默认值。对于简单类型,默认值可以自己设定,例如上例的PhoneNumber中的PhoneType字段。如果没有自行设定,会被赋

8、上一个系统默认值,数字类型会被赋为0,String类型会被赋为空字符串,bool类型会被赋为false。对于内置的message,默认值为该message的默认实例或者原型,即其内所有字段均为设置。当获取没有显式设置值的optional字段的值时,就会返回该字段的默认值。3.repeated:该字段可以重复任意次数,包括0次。重复数据的顺序将会保存在protocol buffer中,将这个字段想象成一个可以自动设置size的数组就可以了。Notice:应该格外小心定义Required字段。当因为某原因要把Required字段改为Optional字段是,会有问题,老版本读取器会认为消息中没有该字

9、段不完整,可能会拒绝或者丢弃该字段(Google文档是这么说的,但是我试了一下,将required的改为optional的,再用原来required时候的解析代码去读,如果字段赋值的话,并不会出错,但是如果字段未赋值,会报这样错误:Exception in thread “main” com.google.protobuf.InvalidProtocolBufferException: Message missing required fields:fieldname)。在设计时,尽量将这种验证放在应用程序端的完成。Google的一些工程师对此也很困惑,他们觉得,required类型坏处大于好

10、处,应该尽量仅适用optional或者repeated的。但也并不是所有的人都这么想。如果想深入学习.proto文件书写,可以参考Protocol Buffer Language Guide。但是不要妄想会有类似于类继承这样的机制,Protocol Buffers不做这个4. 编译Protocol Buffers定义好.proto文件后,接下来,就是使用该文件,运行PB的编译器protoc,编译.proto文件,生成相关类,可以使用这些类读写“通讯簿”没得message。接下来我们要做:1.如果你还没有安装PB编译器,到这里现在安装:download the package2.安装后,运行pr

11、otoc,结束后会发现在项目com.example.tutorial package下,生成了AddressBookProtos.java文件:protoc -I=$SRC_DIR -java_out=$DST_DIR $SRC_DIR/addressbook.proto#for exampleprotoc -I=G:workspaceprotobufmessage -java_out=G:workspaceprotobufsrcmainjava G:workspaceprotobufmessagesaddressbook.proto-I:指明应用程序的源码位置,假如不赋值,则有当前路径(说实

12、话,该处我是直译了,并不明白是什么意思。我做了尝试,该值不能为空,如果为空,则提示赋了一个空文件夹,如果是当前路径,请用.代替,我用.代替,又提示不对。但是可以是任何一个路径,都运行正确,只要不为空);java_out:指明目的路径,即生成代码输出路径。因为我们这里是基于java来说的,所以这里是java_out,相对其他语言,设置为相对语言即可最后一个参数即.proto文件此处运行完毕后,查看生成的代码,很有可能会出现一些类没有定义等错误,例如:com.google cannot be resolved to a type等。这是因为项目中缺少protocol buffers的相应libra

13、ry。在Protocol Buffers的源码包里,你会发现java/src/main/java,将这下边的文件拷贝到你的项目,大概可以解决问题。我只能说大概,因为当时我在弄得时候,也是刚学,各种出错,比较恶心。有一个简单的方法,呵呵,对于懒汉来说。创建一个maven的java项目,在pom.xml中,添加Protocol Buffers的依赖即可解决所有问题在pom.xml中添加如下依赖(注意版本): com.google.protobufartifactIdprotobuf-javaversion2.5.0/dependency5.Protocol Buffer Java API5.1 产

14、生的类及方法接下来看一下PB编译器创建了那些类以及方法。首先会发现一个.java文件,其内部定义了一个AddressBookProtos类,即我们在addressbook.proto文件java_outer_classname 指定的。该类内部有一系列内部类,对应分别是我们在addressbook.proto中定义的message。每个类内部都有相应的Builder类,我们可以用它创建类的实例。生成的类及类内部的Builder类,均自动生成了获取message中字段的方法,不同的是,生成的类仅有getter方法,而生成类内部的Builder既有getter方法,又有setter方法。本例中Pe

15、rson类,其仅有getter方法,如图所示:但是Person.Builder类,既有getter方法,又有setter方法,如图:person.builder从上边两张图可以看到:1.每一个字段都有JavaBean风格的getter和setter2.对于每一个简单类型变量,还对应都有一个has这样的一个方法,如果该字段被赋值了,则返回true,否则,返回false3.对每一个变量,都有一个clear方法,用于置空字段对于repeated字段:repeated filed从图上看:1.从person.builder图上看出,对于repeated字段,还有一个特殊的getter,即getPhon

16、eCount方法,及repeated字段还有一个特殊的count方法2.其getter和setter方法根据index获取或设置一个数据项3.add()方法用于附加一个数据项4.addAll()方法来直接增加一个容器中的所有数据项注意到一点:所有的这些方法均命名均符合驼峰规则,即使在.proto文件中是小写的。PB compiler生成的方法及字段等都是按照驼峰规则来产生,以符合基本的Java规范,当然,其他语言也尽量如此。所以,在proto文件中,命名最好使用用“_”来分割不同小写的单词。5.2 枚举及嵌套类从代码中可以发现,还产生了一个枚举:PhoneType,该枚举位于Person类内部

17、: public enum PhoneType implements com.google.protobuf.ProtocolMessageEnum /* * MOBILE = 0;/code */ MOBILE(0, 0),HOME = 1; HOME(1, 1),WORK = 2; WORK(2, 2), ; .除此之外,如我们所预料,还有一个Person.PhoneNumber内部类,嵌套在Person类中,可以自行看一下生成代码,不再粘贴。5.3 Builders vs. Messages由PB compiler生成的消息类是不可变的。一旦一个消息对象构建出来,他就不再能够修改,就像j

18、ava中的String一样。在构建一个message之前,首先要构建一个builder,然后使用builder的setter或者add()等方法为所需字段赋值,之后调用builder对象的build方法。在使用中会发现,这些构造message对象的builder的方法,都又会返回一个新的builder,事实上,该builder跟调用这个方法的builder是同一方法。这样做的目的,仅是为了方便而已,我们可以把所有的setter写在一行内。如下构造一个Person实例:Person john = Person .newBuilder() .setId(1) .setName(john) .set

19、Email(* .addPhone( PhoneNumber .newBuilder() .setNumber(1861xxxxxxx .setType(PhoneType.WORK) .build() ).build();5.4 标准消息方法每一个消息类及Builder类,基本都包含一些公用方法,用来检查和维护这个message,包括:isInitialized(): 检查是否所有的required字段是否被赋值2.toString(): 返回一个便于阅读的message表示(本来是二进制的,不可读),尤其在debug时候比较有用3.mergeFrom(Message other): 仅bu

20、ilder有此方法,将其message的内容与此message合并,覆盖简单及重复字段4.clear(): 仅builder有此方法,清空所有的字段5.5 解析及序列化对于每一个PB类,均提供了读写二进制数据的方法:1.byte toByteArray();: 序列化message并且返回一个原始字节类型的字节数组2.static Person parseFrom(byte data); 将给定的字节数组解析为message3.void writeTo(OutputStream output); 将序列化后的message写入到输出流4.static Person parseFrom(Inpu

21、tStream input); 读入并且将输入流解析为一个message这里仅列出了几个解析及序列化方法,完整列表,可以参见:MessageAPI reference6. 使用PB生成类写入接下来使用这些生成的PB类,初始化一些联系人,并将其写入一个文件中。下面的程序首先从一个文件中读取一个通讯簿(AddressBook),然后添加一个新的联系人,再将新的通讯簿写回到文件。package com.example.tutorial;import com.example.tutorial.AddressBookProtos.AddressBook;import com.example.tutori

22、al.AddressBookProtos.Person;import java.io.BufferedReader;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.InputStreamReader;import java.io.IOException;import java.io.PrintStream;class AddPerson / This function fills in a Person messa

23、ge based on user input. static Person PromptForAddress(BufferedReader stdin, PrintStream stdout) throws IOException Person.Builder person = Person.newBuilder(); stdout.print(Enter person ID: ); person.setId(Integer.valueOf(stdin.readLine();Enter name: person.setName(stdin.readLine();Enter email addr

24、ess (blank for none): String email = stdin.readLine(); if (email.length() 0) person.setEmail(email); while (true) stdout.print(Enter a phone number (or leave blank to finish): String number = stdin.readLine(); if (number.length() = 0) break; Person.PhoneNumber.Builder phoneNumber = Person.PhoneNumbe

25、r .newBuilder().setNumber(number);Is this a mobile, home, or work phone? String type = stdin.readLine(); if (type.equals(mobile) phoneNumber.setType(Person.PhoneType.MOBILE); else if (type.equals(home phoneNumber.setType(Person.PhoneType.HOME);work phoneNumber.setType(Person.PhoneType.WORK); else st

26、dout.println(Unknown phone type. Using default. person.addPhone(phoneNumber); return person.build(); / Main function: Reads the entire address book from a file, / adds one person based on user input, then writes it back out to the same / file. public static void main(String args) throws Exception if

27、 (args.length != 1) System.err.println(Usage: AddPerson ADDRESS_BOOK_FILE System.exit(-1); AddressBook.Builder addressBook = AddressBook.newBuilder(); / Read the existing address book. try addressBook.mergeFrom(new FileInputStream(args0); catch (FileNotFoundException e) System.out.println(args0 + File not found. Creating a new file. / Add an address. addressBook.addPerson(PromptForAddress(new BufferedReader( new InputStreamReader(System.in), System.out); / Write the new address book b

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1