protobuf 是一种新的数据结构,用于程序之间相互传输。 据说是比XML 、 JSON的效率等一些方面都要优秀。 所以研究了一番,这里做下记录。
目前是支持java、c++、Python 三大语言的
使用protobuf 首先要定义好我们的对象,类似编写xml前先编写(.xsd schema文件一样)
文件的后缀名为.proto
下面是一个例子:school.proto
package school ;
option java_package = "com.zf.school"; //生成的类的包名
option java_outer_classname = "SchoolProtos" ; //生成类的类名
//定义一个对象Student
message Student{
required int32 id = 1; //int32对应java中的Int类型
required string name = 2 ;
optional int32 age = 3;
required string idcard = 4 ;
required bool story = 5 ; //bool对应java中的Boolean类型
repeated Book book = 6 ; //使用repeated修饰,表示该元素可以重复,也就是相当于book是一个List
required SchoolBag bag = 7;
}
message Book{
required string name = 1;
required int32 quantity = 2;
optional string color = 3;
required Book_Type type = 4 [default = OTHER] ; //枚举类型可以通过 [default = value] 设置默认值
}
// 定义一个枚举类型
enum Book_Type{
HISTORY = 1 ;
PHILOSOPHY = 2;
CHEMISTRY = 3;
OTHER = 4 ;
}
message SchoolBag{
required string color = 1 ;
optional Bag_Size size = 2 [default=MIDDLE];
// 在message内部定义枚举类型, 也可以在message内部定义message类型
enum Bag_Size{
BIG = 1 ;
MIDDLE = 2 ;
SMALL = 3;
}
}
如果是在windows目录,就下载从http://code.google.com/p/protobuf/downloads/detail?name=protoc-2.5.0-win32.zip&can=2&q=下载protoc-2.5.0-win32.zip文件,解压后会出现一个protoc.exe文件,将该文件所在的目录加入到系统的环境变量PATH中,之后就可以用protoc来转换.proto文件为Java文件了
然后使用protoc将该proto文件转换为java类
命令:protoc -I=D:\01 --java_out=D:\02 D:\01\school.proto
D:\01 是.proto文件所在的目录 D:\02是生成的java类所存在的目录 最后一个D:\01\school.proto是.proto文件的位置
然后就在 D:\02目录下面生成了一个类SchoolProtos.java,由于这个类比较复杂,太长了,所以就不贴出来了。
之后就可以通过该类来获取我们定义的类型,并操作了。
先在项目中加入protobuf-2.5.0.jar
package com.zf.school;
import com.google.protobuf.InvalidProtocolBufferException;
import com.zf.school.SchoolProtos.Book;
import com.zf.school.SchoolProtos.Book_Type;
import com.zf.school.SchoolProtos.SchoolBag;
import com.zf.school.SchoolProtos.Student;
import com.zf.school.SchoolProtos.SchoolBag.Bag_Size;
public class Test {
public static void main(String[] args) throws InvalidProtocolBufferException {
//创建一个book
Book book = SchoolProtos.Book.newBuilder()
.setColor("RED")
.setName("restlet in action")
.setType(Book_Type.HISTORY)
.setQuantity(1)
.build();
//创建一个bag
SchoolBag bag = SchoolBag.newBuilder()
.setColor("GREEN")
.setSize(Bag_Size.BIG)
.build() ;
//创建一个student
Student stu =SchoolProtos.Student.newBuilder()
.setId(1).setName("zhoufeng")
.setIdcard("45679412316578941")
.setStory(true)
.addBook(book) //注意:因为book在.proto文件中使用repeated修饰,所以这里可以用addBook
.addBook(book)
.setBag(bag) //注意:bag使用的是required修饰,所以只能有一个,并且必须有一个,而不能用addBag
.build();
//打印student的详细信息
System.out.println(stu.toString());
/**
可以通过toByteArray方法将student对象转换为byte数组,然后再网络上传输
byte[] stuBytes = stu.toByteArray() ;
另一端接收到byte数组后可以通过parseFrom方法将byte数组转换为Student对象
Student newStu = SchoolProtos.Student.parseFrom(stuBytes);
*/
}
}
id: 1
name: "zhoufeng"
idcard: "45679412316578941"
story: true
book {
name: "restlet in action"
quantity: 1
color: "RED"
type: HISTORY
}
book {
name: "restlet in action"
quantity: 1
color: "RED"
type: HISTORY
}
bag {
color: "GREEN"
size: BIG
}
看上去这个结构与JSON结构很相似,但还是不同的,比如说book,在上面两个book是分开的,但是在JSON中如果是多个book,肯定是在一个key里面被包含。而不会出现重复的key