ProtocolBuffers教程
程序员文章站
2022-05-21 19:59:18
...
ProtocolBuffers是Google提出的一种二进制的数据交换格式,性能较平常的XML格式提高了不少.它独立于平台和语言,google提供了C++,Java和Python三种语言的实现,通过第三方扩展可以支持更多的语言平台.现在新版本为2.4.1,但是还只提供2.3.0的protoc编译器下载,新版本需要自行编译了.
一下通过Google提供的例子讲解:
1.编写proto文件
ProtocolBuffers是通过定义.Proto文件做为数据交换的接口.文件中写入需要交换的bean.如:
// See README.txt for information and build instructions.
package tutorial;
// 定义包名
option java_package = "com.example.tutorial";
// 定义类名
option java_outer_classname = "AddressBookProtos";
// 定义message类
message Person {
required string name = 1; // required 为必选参数,如果传值为空会抛出IOException
required int32 id = 2; // Unique ID number for this person.
optional string email = 3; // optional 为可选参数.
// 定义枚举类
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber { // 子类
required string number = 1;
optional PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phone = 4; // repeated为可重复参数,通过List实习
}
// Our address book file is just one of these.
message AddressBook {
repeated Person person = 1;
}
注意:等号不是赋值,而是给字段名分配唯一的数字标签,用于升级时的版本兼容性。
该例子定义了一个AddressBook类.Book类中有多个Person类.具体内容详见http://code.google.com/intl/zh-CN/apis/protocolbuffers/docs/proto.html
2.编译proto文件生成相应语言.
使用protoc进行编译:
protoc -I=$SRC_DIR --java_out=$DST_DIR $SRC_DIR/addressbook.proto
其他语言输出使用方法:
protoc --java_out . --cpp_out . --python_out . search_response_protos.proto
编译后生成com/example/tutorial/AddressBookProtos.java的引用类
3.使用proto
分析examples中的AddPerson.java
// See README.txt for information and build instructions.
import com.example.tutorial.AddressBookProtos.AddressBook;
import com.example.tutorial.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 message based on user input.
static Person PromptForAddress(BufferedReader stdin,
PrintStream stdout) throws IOException {
// 构建Builder;类似于StringBuffer的类.
Person.Builder person = Person.newBuilder();
stdout.print("Enter person ID: ");
person.setId(Integer.valueOf(stdin.readLine()));
stdout.print("Enter name: ");
person.setName(stdin.readLine());
stdout.print("Enter email address (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.PhoneNumber.newBuilder().setNumber(number);
stdout.print("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);
} else if (type.equals("work")) {
phoneNumber.setType(Person.PhoneType.WORK);
} else {
stdout.println("Unknown phone type. Using default.");
}
person.addPhone(phoneNumber);
}
// 通过Builder构建返回Message
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 (args.length != 1) {
System.err.println("Usage: AddPerson ADDRESS_BOOK_FILE");
System.exit(-1);
}
// 创建AddressBook Builder.
AddressBook.Builder addressBook = AddressBook.newBuilder();
// Read the existing address book.
try {
FileInputStream input = new FileInputStream(args[0]);
addressBook.mergeFrom(input);
input.close();
} catch (FileNotFoundException e) {
System.out.println(args[0] + ": 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 back to disk.
FileOutputStream output = new FileOutputStream(args[0]);
addressBook.build().writeTo(output);
output.close();
}
}
参见:http://code.google.com/intl/zh-CN/apis/protocolbuffers/docs/reference/java-generated.html执行:
javac -d . -classpath .;protobuf-java-2.4.1.jar AddPerson.java ListPeople.java com\example\tutorial\AddressBookProtos.java
报错:
查看AddressBookProtos.java发现2.4.1中GeneratedMessage提供了一个新的空方法需要实现,覆盖该空方法.
重新编译成功,生成class类.
4. 测试
利用接口调用AddPerson添加Person.
java -cp .;protobuf-java-2.4.1.jar AddPerson addr.dat
利用接口调用ListPeople查找添加的Person.
java -cp .;protobuf-java-2.4.1.jar ListPeople addr.dat
5.参考资料