- 浏览: 537946 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
landerson:
明显就有要求的嘛
ANDROID轻量级JSON序列化和反序列化[转] -
jimode2013:
很不错,就是需要这个方法
多个UIViewController使用addSubView,第二个 UIViewController 不响应旋转[转] -
w11h22j33:
...
[转]NSMutableArray中的自动释放对象让我郁闷了一整天 -
w11h22j33:
UILabel* label = [[UILabel a ...
Iphone开发 -
w11h22j33:
http://mobile.51cto.com/iphone- ...
获得通讯录中联系人的所有属性[转]
目录 1 概览 欢迎来到protocol buffer的开发者指南文档,一种语言无关、平台无关、扩展性好的用于通信协议、数据存储的结构化数据串行化方法。 本文档面向希望使用protocol buffer的Java、C++或Python开发者。这个概览介绍了protocol buffer,并告诉你如何开始,你随后可以跟随编程指导( http://code.google.com/apis/protocolbuffers/docs/tutorials.html )深入了解protocol buffer编码方式( http://code.google.com/apis/protocolbuffers/docs/encoding.html )。API参考文档( http://code.google.com/apis/protocolbuffers/docs/reference/overview.html )同样也是提供了这三种编程语言的版本,不够协议语言( http://code.google.com/apis/protocolbuffers/docs/proto.html )和样式( http://code.google.com/apis/protocolbuffers/docs/style.html )指导都是编写 .proto 文件。 1.1 什么是protocol buffer ProtocolBuffer是用于结构化数据串行化的灵活、高效、自动的方法,有如XML,不过它更小、更快、也更简单。你可以定义自己的数据结构,然后使用代码生成器生成的代码来读写这个数据结构。你甚至可以在无需重新部署程序的情况下更新数据结构。 1.2 他们如何工作 你首先需要在一个 .proto 文件中定义你需要做串行化的数据结构信息。每个ProtocolBuffer信息是一小段逻辑记录,包含一系列的键值对。这里有个非常简单的 .proto 文件定义了个人信息: message Person { 有如你所见,消息格式很简单,每个消息类型拥有一个或多个特定的数字字段,每个字段拥有一个名字和一个值类型。值类型可以是数字(整数或浮点)、布尔型、字符串、原始字节或者其他ProtocolBuffer类型,还允许数据结构的分级。你可以指定可选字段,必选字段和重复字段。你可以在( http://code.google.com/apis/protocolbuffers/docs/proto.html )找到更多关于如何编写 .proto 文件的信息。 一旦你定义了自己的报文格式(message),你就可以运行ProtocolBuffer编译器,将你的 .proto 文件编译成特定语言的类。这些类提供了简单的方法访问每个字段(像是 query()和 set_query() ),像是访问类的方法一样将结构串行化或反串行化。例如你可以选择C++语言,运行编译如上的协议文件生成类叫做 Person 。随后你就可以在应用中使用这个类来串行化的读取报文信息。你可以这么写代码: Person person; 然后,你可以读取报文中的数据: fstream input("myfile",ios::in | ios:binary); 你可以在不影响向后兼容的情况下随意给数据结构增加字段,旧有的数据会忽略新的字段。所以如果使用ProtocolBuffer作为通信协议,你可以无须担心破坏现有代码的情况下扩展协议。 你可以在API参考( http://code.google.com/apis/protocolbuffers/docs/reference/overview.html )中找到完整的参考,而关于ProtocolBuffer的报文格式编码则可以在( http://code.google.com/apis/protocolbuffers/docs/encoding.html )中找到。 1.3 为什么不用XML? ProtocolBuffer拥有多项比XML更高级的串行化结构数据的特性,ProtocolBuffer: · 更简单 · 小3-10倍 · 快20-100倍 · 更少的歧义 · 可以方便的生成数据存取类 例如,让我们看看如何在XML中建模Person的name和email字段: <person> 对应的ProtocolBuffer报文则如下: #ProtocolBuffer的文本表示 当这个报文编码到ProtocolBuffer的二进制格式( http://code.google.com/apis/protocolbuffers/docs/encoding.html )时(上面的文本仅用于调试和编辑),它只需要28字节和100-200ns的解析时间。而XML的版本需要69字节(除去空白)和5000-10000ns的解析时间。 当然,操作ProtocolBuffer也很简单: cout << "Name: " << person.name() << endl; 而XML的你需要: cout << "Name: " 当然,ProtocolBuffer并不是在任何时候都比XML更合适,例如ProtocolBuffer无法对一个基于标记文本的文档建模,因为你根本没法方便的在文本中插入结构。另外,XML是便于人类阅读和编辑的,而ProtocolBuffer则不是。还有XML是自解释的,而 ProtocolBuffer仅在你拥有报文格式定义的 .proto 文件时才有意义。 1.4 听起来像是为我的解决方案,如何开始? 下载包( http://code.google.com/p/protobuf/downloads/ ),包含了Java、Python、C++的ProtocolBuffer编译器,用于生成你需要的IO类。构建和安装你的编译器,跟随README的指令就可以做到。 一旦你安装好了,就可以跟着编程指导( http://code.google.com/apis/protocolbuffers/docs/tutorials.html )来选择语言-随后就是使用ProtocolBuffer创建一个简单的应用了。 1.5 一点历史 ProtocolBuffer最初是在Google开发的,用以解决索引服务器的请求、响应协议。在使用ProtocolBuffer之前,有一种格式用以处理请求和响应数据的编码和解码,并且支持多种版本的协议。而这最终导致了丑陋的代码,有如: if (version==3) { 通信协议因此变得越来越复杂,因为开发者必须确保,发出请求的人和接受请求的人必须同时兼容,并且在一方开始使用新协议时,另外一方也要可以接受。 ProtocolBuffer设计用于解决这一类问题: · 很方便引入新字段,而中间服务器可以忽略这些字段,直接传递过去而无需理解所有的字段。 · 格式可以自描述,并且可以在多种语言中使用(C++、Java等) 然而用户仍然需要手写解析代码。 随着系统的演化,他需要一些其他的功能: · 自动生成编码和解码代码,而无需自己编写解析器。 · 除了用于简短的RPC(Remote Procedure Call)请求,人们使用ProtocolBuffer来做数据存储格式(例如BitTable)。 · RPC服务器接口可以作为 .proto 文件来描述,而通过ProtocolBuffer的编译器生成存根(stub)类供用户实现服务器接口。 ProtocolBuffer现在已经是Google的混合语言数据标准了,现在已经正在使用的有超过48,162种报文格式定义和超过12,183个 .proto 文件。他们用于RPC系统和持续数据存储系统。 2 语言指导 本指导描述了如何使用ProtocolBuffer语言来定义结构化数据类型,包括 .proto 文件的语法和如何生成存取类。 这是一份指导手册,一步步的例子使用文档中的多种功能,查看入门指导( http://code.google.com/apis/protocolbuffers/docs/tutorials.html )选择你的语言。 2.1 定义一个消息类型 @waiting … 2.2 值类型 @waiting … 2.3 可选字段与缺省值 @waiting … 2.4 枚举 @waiting … 2.5 使用其他消息类型 @waiting … 2.6 嵌套类型 @waiting … 2.7 更新一个数据类型 @waiting … 2.8 扩展 @waiting … 2.9 包 @waiting … 2.10 定义服务 @waiting … 2.11 选项 @waiting … 2.12 生成你的类 @waiting … 3 代码风格指导 本文档提供了 .proto 文件的代码风格指导。按照惯例,你将会,你将会生成一些便于阅读和一致的ProtocolBuffer定义文件。 3.1 消息与字段名 使用骆驼风格的大小写命名,即单词首字母大写,来做消息名。使用GNU的全部小写,使用下划线分隔的方式定义字段名: message SongServerRequest { 使用这种命名方式得到的名字如下: C++: 3.2 枚举 使用骆驼风格做枚举名,而用全部大写做值的名字: enum Foo { 每个枚举值最后以分号结尾,而不是逗号。 3.3 服务 如果你的 .proto 文件定义了RPC服务,你可以使用骆驼风格: service FooService { 4 编码 本文档描述了ProtocolBuffer的串行化二进制数据格式定义。你如果仅仅是在应用中使用ProtocolBuffer,并不需要知道这些,但是这些会对你定义高效的格式有所帮助。 4.1 一个简单的消息 @waiting … 4.2 基于128的Varints @waiting … 4.3 消息结构 @waiting … 4.4 更多的值类型 @waiting … 4.5 内嵌消息 @waiting … 4.6 可选的和重复的元素 @waiting … 4.7 字段顺序 @waiting … 5 ProtocolBuffer基础:C++ @waiting … 6 ProtocolBuffer基础:Java @waiting … 7 ProtocolBuffer基础:Python 本指南给Python程序员一个快速使用的ProtocolBuffer的指导。通过一些简单的例子来在应用中使用ProtocolBuffer,它向你展示了如何: · 定义 .proto 消息格式文件 · 使用ProtocolBuffer编译器 · 使用Python的ProtocolBuffer编程接口来读写消息 这并不是一个在Python中使用ProtocolBuffer的完整指导。更多细节请参考手册信息,查看语言指导( http://code.google.com/apis/protocolbuffers/docs/proto.html ),Python API( http://code.google.com/apis/protocolbuffers/docs/reference/python/index.html ),和编码手册( http://code.google.com/apis/protocolbuffers/docs/encoding.html )。 7.1 为什么使用ProtocolBuffer? 下面的例子”地址本”应用用于读写人的联系信息。每个人有name、ID、email,和联系人电话号码。 如何串行化和读取结构化数据呢?有如下几种问题: · 使用Python的pickle,这是语言内置的缺省方法,不过没法演化,也无法让其他语言支持。 · 你可以发明一种数据编码方法,例如4个整数”12:3-23:67″,这是简单而灵活的方法,不过你需要自己写解析器代码,且只适用于简单的数据。 · 串行化数据到XML。这种方法因为可读性和多种语言的兼容函数库而显得比较吸引人,不过这也不是最好的方法,因为XML浪费空间是臭名昭著的,编码解码也很浪费时间。而XML DOM树也是很复杂的。 ProtocolBuffer提供了灵活、高效、自动化的方法来解决这些问题。通过ProtocolBuffer,只需要写一个 .proto 数据结构描述文件,就可以编译到几种语言的自动编码解码类。生成的类提供了setter和getter方法来控制读写细节。最重要的是 ProtocolBuffer支持后期扩展协议,而又确保旧格式可以兼容。 7.2 哪里可以找到例子代码 源码发行包中已经包含了,在”example”文件夹。 7.3 定义你的协议格式 想要创建你的地址本应用,需要开始于一个 .proto 文件。定义一个 .proto 文件很简单:添加一个消息到数据结构,然后指定一个和一个类型到每一个字段,如下是本次例子使用的 addressbook.proto package tutorial; 有如你所见的,语法类似于C++或Java。让我们分块理解他们。 @waiting … 7.4 编译你的ProtocolBuffer 现在已经拥有了 .proto 文件,下一步就是编译生成相关的访问类。运行编译器 protoc 编译你的 .proto 文件。 1. 如果还没安装编译器则下载并按照README的安装。 2. 运行编译器,指定源目录和目标目录,定位你的 .proto 文件到源目录,然后执行: protoc -I=$SRC_DIR --python_out=$DST_DIR addressbook.proto 因为需要使用Python类,所以 –python_out 选项指定了特定的输出语言。 这个步骤会生成 addressbook_pb2.py 到目标目录。 7.5 ProtocolBuffer API 不像生成的C++和Java代码,Python生成的类并不会直接为你生成存取数据的代码。而是(有如你在 addressbook_pb2.py 中见到的)生成消息描述、枚举、和字段,还有一些神秘的空类,每个对应一个消息类型: class Person(message.Message): 这里每个类最重要的一行是 __metaclass__=reflection.GeneratedProtocolMessageType 。通过Python的元类机制工作,你可以把他们看做是生成类的模板。在载入时,GeneratedProtocolMessageType 元类使用特定的描述符创建Python方法。随后你就可以使用完整的功能了。 最后就是你可以使用 Person 类来操作相关字段了。例如你可以写: import addressbook_pb2 需要注意的是这些赋值属性并不是简单的增加新字段到Python对象,如果你尝试给一个 .proto 文件中没有定义的字段赋值,就会抛出 AttributeError 异常,如果赋值类型错误会抛出 TypeError 。在给一个字段赋值之前读取会返回缺省值: person.no_such_field=1 #raise AttributeError 更多相关信息参考( http://code.google.com/apis/protocolbuffers/docs/reference/python-generated.html )。 7.5.1 枚举 枚举在元类中定义为一些符号常量对应的数字。例如常量 addressbook_pb2.Person.WORK 拥有值2。 7.5.2 标准消息方法 每个消息类包含一些其他方法允许你检查和控制整个消息,包括: · IsInitialized() :检查是否所有必须(required)字段都已经被赋值了。 · __str__() :返回人类可读的消息表示,便于调试。 · CopyFrom(other_msg) :使用另外一个消息的值来覆盖本消息。 · Clear() :清除所有元素的值,回到初识状态。 这些方法是通过接口 Message 实现的,更多消息参考( http://code.google.com/apis/protocolbuffers/docs/reference/python/google.protobuf.message.Message-class.html )。 7.5.3 解析与串行化 最后,每个ProtocolBuffer类有些方法用于读写消息的二进制数据( http://code.google.com/apis/protocolbuffers/docs/encoding.html )。包括: · SerializeToString() :串行化,并返回字符串。注意是二进制格式而非文本。 · ParseFromString(data) :解析数据。 他们是成对使用的,提供二进制数据的串行化和解析。另外参考消息API参考( http://code.google.com/apis/protocolbuffers/docs/reference/python/google.protobuf.message.Message-class.html )了解更多信息。 Note ProtocolBuffer与面向对象设计 ProtocolBuffer类只是用于存取数据的,类似于C++中的结构体,他们并没有在面向对象方面做很好的设计。如果你想要给这些类添加更多的行为,最好的方法是包装(wrap)。包装同样适合于复用别人写好的 .proto 文件。这种情况下,你可以把ProtocolBuffer生成类包装的很适合于你的应用,并隐藏一些数据和方法,暴露有用的函数等等。 你不可以通过继承来给自动生成的类添加行为。 这会破坏他们的内部工作机制。 7.6 写消息 现在开始尝试使用ProtocolBuffer的类。第一件事是让地址本应用可以记录联系人的细节信息。想要做这些需要先创建联系人实例,然后写入到输出流。 这里的程序从文件读取地址本,添加新的联系人信息,然后写回新的地址本到文件。 #! /usr/bin/python 7.7 读消息 当然,一个无法读取的地址本是没什么用处的,这个例子读取刚才创建的文件并打印所有信息: #! /usr/bin/python 7.8 扩展ProtocolBuffer 在你发不了代码以后,可能会想要改进ProtocolBuffer的定义。如果你想新的数据结构向后兼容,而你的旧数据可以向前兼容,那么你就找对了东西了,不过有些规则需要遵守。在新版本的ProtocolBuffer中: · 必须不可以改变已经存在的标签的数字。 · 必须不可以增加或删除必须(required)字段。 · 可以删除可选(optional)或重复(repeated)字段。 · 可以添加新的可选或重复字段,但是必须使用新的标签数字,必须是之前的字段所没有用过的。 这些规则也有例外( http://code.google.com/apis/protocolbuffers/docs/proto.html#updating ),不过很少使用。 如果你遵从这些规则,旧代码会很容易的读取新的消息,并简单的忽略新的字段。而对旧的被删除的可选字段也会简单的使用他们的缺省值,被删除的重复字段会自动为空。新的代码也会透明的读取旧的消息。然而,需要注意的是新的可选消息不会在旧的消息中显示,所以你需要使用 has_ 严格的检查他们是否存在,或者在 .proto 文件中提供一个缺省值。如果没有缺省值,就会有一个类型相关的默认缺省值:对于字符串就是空字符串;对于布尔型则是false;对于数字类型默认为0。同时要注意的是如果你添加了新的重复字段,你的新代码不会告诉你这个字段为空(新代码)也不会,也不会(旧代码)包含 has_ 标志。 7.9 高级使用 ProtocolBuffer不仅仅提供了数据结构的存取和串行化。查看Python API参考( http://code.google.com/apis/protocolbuffers/docs/reference/python/index.html )了解更多功能。 一个核心功能是通过消息类的映射(reflection)提供的。你可以通过它遍历消息的所有字段,和管理他们的值。关于映射的一个很有用的地方是转换到其他编码,如XML或JSON。一个使用映射的更高级的功能是寻找同类型两个消息的差异,或者开发出排序、正则表达式等功能。使用你的创造力,还可以用ProtocolBuffer实现比你以前想象的更多的问题。 映射是通过消息接口提供的。 8 参考概览 @waiting … 9 C++代码生成 @waiting … 10 C++ API @waiting … 11 Java代码生成 @waiting … 12 Java API @waiting … 13 Python代码生成 本页提供了Python生成类的相关细节。你可以在阅读本文档之前查看语言指导。 Python的ProtocolBuffer实现与C++和Java的略有不同,编译器只输出构建代码的描述符来生成类,而由Python的元类来执行工作。本文档描述了元类开始生效以后的东西。 13.1 编译器的使用 ProtocolBuffer通过编译器的 –python_out= 选项来生成Python的相关类。这个参数实际上是指定输出的Python类放在哪个目录下。编译器会为每个 .proto 文件生成一个对应的 .py 文件。输出文件名与输入文件名相关,不过有两处修改: · 扩展名 .proto 改为 .py 。 · 路径名的修改。 如果你按照如下调用编译器: protoc --proto_path=src --python_out=build/gen src/foo.proto src/bar/baz.proto 编译器会自动读取两个 .proto 文件然后产生两个输出文件。在需要时编译器会自动创建目录,不过 –python_out 指定的目录不会自动创建。 需要注意的是,如果 .proto 文件名或路径包含有无法在Python中使用的模块名(如连字符),就会被自动转换为下划线。所以文件 foo-bar.proto 会变成 foo_bar_pb2.py 。 Note 在每个文件后缀的 _pb2.py 中的2代表ProtocolBuffer版本2。版本1仅在Google内部使用,但是你仍然可以在以前发布的一些代码中找到它。自动版本2开始,ProtocolBuffer开始使用完全不同的接口了,从此Python也没有编译时类型检查了,我们加上这个版本号来标志Python文件名。 13.2 包 Python代码生成根本不在乎包的名字。因为Python使用目录名来做包名。 13.3 消息 先看看一个简单的消息声明: message Foo {} ProtocolBuffer编译器会生成类Foo,它是 google.protobuf.Message 的子类。这个实体类,不含有虚拟方法。不像C++和Java,Python生成类对优化选项不感冒;实际上Python的生成代码已经为代码大小做了优化。 你不能继承Foo的子类。生成类被设计不可以被继承,否则会被打破一些设计。另外,继承本类也是不好的设计。 Python的消息类没有特定的公共成员,而是定义接口,极其嵌套的字段、消息和枚举类型。 一个消息可以在另外一个消息中声明,例如 message Foo { message Bar {}} 。在这种情况下,Bar类定义为Foo的一个静态成员,所以你可以通过 Foo.Bar 来引用。 13.4 字段 对于消息类型中的每一个字段,都有对应的同名成员。 13.4.1 简单字段 如果你有一个简单字段(包括可选的和重复的),也就是非消息字段,你可以通过简单字段的方式来管理,例如foo字段的类型是int32,你可以: message.foo=123 注意设置foo的值,如果类型错误会抛出TypeError。 如果foo在赋值之前就读取,就会使用缺省值。想要检查是否已经赋值,可以用 HasField() ,而清除该字段的值用 ClearField() 。例如: assert not message.HasField("foo") 13.4.2 简单消息字段 消息类型工作方式略有不同。你无法为一个嵌入消息字段赋值。而是直接操作这个消息的成员。因为实例化上层消息时,其包含的子消息同时也实例化了,例如定义: message Foo { 你不可以这么做,因为不能做消息类型字段的赋值: foo=Foo() 而是可以直接对消息类型字段的成员赋值: foo=Foo() 注意简单的读取消息类型字段的未赋值成员只不过是打印其缺省值: foo=Foo() 13.4.3 重复字段 重复字段表现的像是Python的序列类型。如果是嵌入的消息,你无法为字段直接赋值,但是你可以管理。例如给定的定义: message Foo { 你就可以这么做: foo=Foo() 作为一种简单字段,清除该字段必须使用 ClearField() 。 13.4.4 重复消息字段 重复消息字段工作方式与重复字段很像,除了 add() 方法用于返回新的对象以外。例如如下定义: message Foo { 你可以这么做: foo=Foo() 13.4.5 枚举类型 @waiting … 13.4.6 扩展 @waiting … 13.5 服务 13.5.1 接口 一个简单的接口定义: service Foo { ProtocolBuffer的编译器会生成类 Foo 来展示这个服务。 Foo 将会拥有每个服务定义的方法。在这种情况下 Bar 方法的定义是: def Bar(self,rpc_controller,request,done) 参数等效于 Service.CallMethod() ,除了隐含的 method_descriptor 参数。 这些生成的方法被定义为可以被子类重载。缺省实现只是简单的调用 controller.SetFailed() 而抛出错误信息告之尚未实现。然后调用done回调。在实现你自己的服务时,你必须继承生成类,然后重载各个接口方法。 Foo继承了 Service 接口。ProtocolBuffer编译器会自动声响相关的实现方法: · GetDescriptor :返回服务的 ServiceDescriptor 。 · CallMethod :检测需要调用哪个方法,并且直接调用。 · GetRequestClass 和 GetResponseClass :返回指定方法的请求和响应类。 13.5.2 存根(Stub) ProtocolBuffer编译器也会为每个服务接口提供一个存根实现,用于客户端发送请求到服务器。对于Foo服务,存根实现是 Foo_Stub 。 Foo_Stub 是Foo的子类,他的构造器是一个 RpcChannel 。存根会实现调用每个服务方法的 CallMethod() 。 ProtocolBuffer哭并不包含RPC实现。然而,它包含了你构造服务类的所有工具,不过选择RPC实现则随你喜欢。你只需要提供 RpcChannel 和 RpcController 的实现即可。 14 Python API @waiting … 15 其他语言 http://www.cppblog.com/liquidx
required string name=1;
required int32 id=2;
optional string email=3;
enum PhoneType {
MOBILE=0;
HOME=1;
WORK=2;
}
message PhoneNumber {
required string number=1;
optional PhoneType type=2 [default=HOME];
}
repeated PhoneNumber phone=4;
}
person.set_name("John Doe");
person.set_id(1234);
person.set_email("jdoe@example.com");
fstream.output("myfile",ios::out | ios::binary);
person.SerializeToOstream(&output);
Person person;
person.ParseFromIstream(&input);
cout << "Name: " << person.name() << endl;
cout << "E-mail: " << person.email() << endl;
<name>John Doe</name>
<email>jdoe@example.com</email>
</person>
#这不是正常时使用的二进制数据
person {
name: "John Doe"
email: "jdoe@example.com"
}
cout << "E-mail: " << person.email() << endl;
<< person.getElementsByTagName("name")->item(0)->innerText()
<< endl;
cout << "E-mail: "
<< person.getElementsByTagName("email")->item(0)->innerText()
<< end;
...
}else if (version>4) {
if (version==5) {
...
}
...
}
required string song_name=1;
}
const string& song_name() {...}
void set_song_name(const string& x) {...}
Java:
public String getSongName() {...}
public Builder setSongName(String v) {...}
FIRST_VALUE=1;
SECOND_VALUE=2;
}
rpc GetSomething(FooRequest) returns (FooResponse);
}
message Person {
required string name=1;
required int32 id=2;
optional string email=3;
enum PhoneType {
MOBILE=0;
HOME=1;
WORK=2;
}
message PhoneNumber {
required string number=1;
optional PhoneType type=2 [default=HOME];
}
repeated PhoneNumber phone=4;
}
message AddressBook {
repeated Person person=1;
}
__metaclass__=reflection.GeneratedProtocolMessageType
class PhoneNumber(message.Message):
__metaclass__=reflection.GeneratedProtocolMessageType
DESCRIPTION=_PERSON_PHONENUMBER
DESCRIPTOR=_PERSON
class AddressBook(message.Message):
__metaclass__=reflection.GeneratedProtocolMessageType
DESCRIPTOR=_ADDRESSBOOK
person=addressbook_pb2.Person()
person.id=1234
person.name="John Doe"
person.email="jdoe@example.com"
phone=person.phone.add()
phone.number="555-4321"
phone.type=addressbook_pb2.Person.HOME
person.id="1234" #raise TypeError
import addressbook_pb2
import sys
#这个函数使用用户输入填充联系人信息
def PromptForAddress(person):
person.id=int(raw_input("Enter person ID number: "))
person.name=raw_input("Enter name: ")
email=raw_input("Enter email address (blank for none): ")
if email!="":
person.email=email
while True:
number=raw_input("Enter a phone number (or leave blank to finish): ")
if number=="":
break
phone_number=person.phone.add()
phone_number.number=number
type=raw_input("Is this a mobile, home, or work phone? ")
if type=="mobile":
phone_number.type=addressbook_pb2.Person.MOBILE
elif type=="home":
phone_number.type=addressbook_pb2.Person.HOME
elif type=="work":
phone_number.type=addressbook_pb2.Person.WORK
else:
print "Unknown phone type; leaving as default value."
#主函数,从文件读取地址本,添加新的联系人,然后写回到文件
if len(sys.argv)!=2:
print "Usage:",sys.argv[0],"ADDRESS_BOOK_FILE"
sys.exit(-1)
address_book=addressbook_pb2.AddressBook()
#读取已经存在的地址本
try:
f=open(sys.argv[1],"fb")
address_book.ParseFromString(f.read())
f.close()
except OSError:
print sys.argv[1]+": Count open file. Creating a new one."
#添加地址
PromptFromAddress(address_book.person.add())
#写入到文件
f=open(sys.argv[1],"wb")
f.write(address_book.SerializeToString())
f.close()
import addressbook_pb2
import sys
#遍历地址本中所有的人并打印出来
def ListPeople(address_book):
for person in address_book.person:
print "Person ID:",person.id
print " Name:",person.name
if person.HasField("email"):
print " E-mail:",person.email
for phone_number in person.phone:
if phone_number.type==addressbook_pb2.Person.MOBILE:
print " Mobile phone #:",
elif phone_number.type==addressbook_pb2.Person.HOME:
print " Home phone #:",
elif phone_number.type==addressbook_pb2.Person.WORK:
print " Work phone #:",
print phone_number.number
#主函数,从文件读取地址本
if len(sys.argv)!=2:
print "Usage:",sys.argv[0],"ADDRESS_BOOK_FILE"
sys.exit(-1)
address_book=addressbook_pb2.AddressBook()
#读取整个地址本文件
f=open(sys.argv[1],"rb")
address_book.ParseFromString(f.read())
f.close()
ListPeople(address_book)
print message.foo
message.foo=123
assert message.HasField("foo")
message.ClearField("foo")
assert not message.HasField("foo")
optional Bar bar=1;
}
message bar {
optional int32 i=1;
}
foo.bar=Bar() #WRONG!
assert not foo.HasField("bar")
foo.bar.i=1
assert foo.HasField("bar")
assert not foo.HasField("bar")
print foo.bar.i #打印i的缺省值
assert not foo.HasField("bar")
repeated int32 nums=1;
}
foo.nums.append(15)
foo.nums.append(32)
assert len(foo.nums)==2
assert foo.nums[0]==15
assert foo.nums[1]==32
for i in foo.nums:
print i
foo.nums[1]=56
assert foo.nums[1]==56
repeated Bar bar=1;
}
message Bar {
optional int32 i=1;
}
bar=foo.bars.add()
bar.i=15
bar=foo.bars.add()
bar.i=32
assert len(foo.bars)==2
assert foo.bars[0].i==15
assert foo.bars[1].i==32
for bar in foo.bars:
print bar.i
foo.bars[1].i=56
assert foo.bars[1].i==56
rpc Bar(FooRequest) returns(FooResponse);
}
http://hi.baidu.com/lee_shine/blog/item/b0386bfd757a4092b901a0fa.html
引自:
发表评论
-
思考、学习新技术的原则和方式【转】
2014-01-02 17:50 1107http://kb.cnblogs.com/page/195 ... -
最好的程序员凡事先上谷歌搜索【转】
2013-03-07 18:07 1297我知道的最优秀的程序员是我的Framebase.io ... -
史上最最佳软件开发实践指导【转】
2013-03-07 18:06 1261“” 阅读器 软件开发 -
我所钟爱的代码审查【转】
2013-02-22 18:00 927当我从学术界转向产业界的过程中,对我生涯改变最大的事情就 ... -
高效代码审查的十个经验【转】
2013-02-22 17:59 976代码审查(Code Review)是软件开发中常用的手段,和 ... -
为什么程序员不擅长评估开发时间?[转]
2012-12-17 10:07 850一个曾经与我一起工作过的经验丰富的项目经理声称,他拿到程 ... -
给明年依然年轻的我们[转]
2012-06-28 09:18 930今天是22岁的最后一天。几个月前,我从沃顿商学院毕业,用 ... -
[转]用户交互设计UI参考书目整理
2012-01-19 15:18 1149书名 作者用户体验的要素 Jesse James Garret ... -
【转】android与PC,C#与Java 利用protobuf 进行无障碍通讯【Socket】
2011-09-07 18:23 2520protobuf 是什么? Protocol ... -
【转】开源点评:Protocol Buffers介绍
2011-09-07 17:14 1172引自:http://blog.csdn.net/p ... -
hg clone 命令的windows解决方法TortoiseHg[转]
2011-05-11 20:50 2330hg是跟svn和cvs一样的版本管理系统。windows下 ... -
谷歌高效能经理人的8个习惯【转】
2011-03-26 12:24 1198Google's "people operati ... -
面试时不要说的7件事【转】
2011-03-26 11:55 9857 Things Not to Say During ... -
为了成功 训练自己[转]
2011-03-26 11:50 1291你是否曾见过像曼尼· ... -
在github上建立自己的开源项目
2011-03-26 00:12 1987由于代码一直在自己这保存,一方面别人看不见,也不安全。搜了下, ... -
从ant到maven -- maven pom例子(初级)转
2011-02-27 00:46 1512http://hi.baidu.com/javajiwei/b ... -
从一个男人身上看出他的修养和抱负
2011-02-15 23:07 858一、拥有自信和风度 男人到了二十几岁后,就要开始学着用心去经营 ... -
用CVS来管理自己的程序
2011-01-15 18:18 905每个编写程序的人也许 ... -
手机操作系统三国时代的结束
2011-01-11 00:19 957第一篇:Symbian正式崩盘,手机操作系统三国时代结束 ... -
如何使用搜索技巧来成为一名高效的程序员
2011-01-11 00:05 838没有人是完全独立的孤 ...
相关推荐
【Protocol Buffer(简称ProtoBuf)开发者指南 - 非官方不完整版】 Protocol Buffer是一种强大的、跨语言的数据序列化协议,由Google开发。它提供了一种高效、灵活且语言无关的方式来处理结构化数据,用于通信协议...
**Protobuf 快速指南中文版** Protocol Buffers(简称Protobuf)是谷歌推出的一种高效的数据序列化协议,它提供了一种语言无关、平台无关、可扩展的序列化方法,与XML类似,但在效率和简洁性上更胜一筹。通过使用...
**ProtoBuf开发者指南** Google Protobuf(Protocol Buffers)是一种数据序列化协议,它允许开发者定义数据结构,并将其转换为二进制格式进行存储或网络传输。作为一种高效、跨平台的序列化工具,Protobuf在分布式...
protobuf全称是Protocol Buffers,是由Google开发的一种数据序列化协议,它允许开发者定义数据结构,然后将数据编码为二进制格式,用于存储或网络传输。标题中的"google protobuf-3.2.0"指的是protobuf的3.2.0版本,...
3. `readme.txt`:这是一个使用文档,通常会包含安装指南、使用方法和常见问题解答,对于初学者来说,它是快速理解和使用protobuf的重要资源。 protobuf的工作流程主要包括以下步骤: 1. **定义数据结构**:使用....
protobuf开发指南旨在帮助开发者了解和使用Google的Protocol Buffers(简称PB),这是一种高效、语言中立、平台中立的结构化数据序列化方法。PB在数据存储和通信协议中广泛应用于Google内部。与XML相比,protobuf...
**Google Protobuf简介** Google Protocol Buffers...通过阅读提供的PDF文档,你将进一步了解Protobuf的Java生成代码细节、编码规则、基础用法以及开发者指南。这些文档将帮助你深入理解Protobuf的使用和最佳实践。
在标题提到的"GoogleProtobuf构建工具"中,我们通常会得到一套包含编译器和库的软件包,以帮助开发者在自己的项目中集成和使用Protobuf。在描述中提到的是版本3.19.1,适用于Windows 64位操作系统,并且提到了获取更...
Google Protocol Buffers(简称protobuf)是由Google开发的一种数据序列化格式,它是一种轻量级、高效、自动化的机制用于序列化结构化数据。protobuf的设计目标是提供一种语言无关、平台无关的扩展性方式用于网络...
"readme.txt"文件通常会提供一些使用指南或版本信息,帮助开发者更好地理解和使用protobuf。 protobuf的优势在于它的性能、灵活性和跨平台性。它支持多种编程语言,使得数据交换变得简单。此外,protobuf还提供了一...
10. **语言和风格指南**:为了编写清晰、可维护的.proto文件,谷歌提供了.proto文件的编码规范和风格指南,有助于团队保持一致性。 在实际项目中,protobuf广泛用于实现高效的数据交换,例如服务器之间的通信、...
本文档旨在为Java、C++或Python开发者提供如何在应用程序中使用protobuf的指南。 #### 二、何为 Protocol Buffers? Protocol Buffers 提供了一种灵活、高效、自动化的机制来序列化结构化数据。它与XML相比体积更...
5. **文档**:可能包括API参考、用户指南等,帮助开发者理解和使用protobuf。 6. **安装脚本或指南**:指导用户如何在Windows 64位系统上安装和配置protobuf环境。 protobuf在数据存储中的应用广泛,它可以用来存储...
谷歌的PROTOBUF(Protocol Buffers)是一种数据序列化协议,它允许开发者定义数据结构的模式,然后将这些数据结构转化为二进制格式进行存储或网络传输。这种格式比XML、JSON等文本格式更紧凑,传输效率更高。在C语言...
Protocol Buffers是Google开发的一种数据序列化协议,它允许开发者定义数据结构,然后生成能够在各种编程语言之间无缝交换这些数据的代码。这种技术广泛应用于分布式系统、网络通信以及数据存储等领域,因其高效的...
Protobuf(Protocol Buffers)是Google推出的一种数据序列化协议,它提供了一种语言中立、平台中立、可扩展的方式来组织数据,类似于XML和JSON,但更高效、更小且更快。在3.20.2版本中,我们关注的是其性能优化、新...
标题中的"protobuf-2.3.0.rar"指的是Google开源的Protocol Buffers(简称protobuf)的2.3.0版本的源代码压缩包。Protocol Buffers是一种高效、跨平台的数据序列化协议,常用于网络通信和数据存储。它能够将结构化...
开发者可以使用protobuf编译器将.proto文件转换为Python等语言的源代码,这些源代码提供了方便的数据序列化和反序列化API。这使得不同系统间交换数据变得更加便捷,因为它们都可以使用protobuf编译器生成的代码来...
4. **文档和示例**: 可能包含API参考文档、用户指南或者示例代码,帮助开发者快速理解和使用protobuf-csharp库。 5. **构建脚本和配置文件**: 用于构建和打包库的工具和配置,例如MSBuild脚本或NuGet配置。 在实际...