Protocol Buffers (简称Protobuf)是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。目前提供了 C++、Java、Python 三种语言的 API。本文是以java语言为编码的示例。
软件:protoc-2.6.1
依赖:jdk1.7
开发环境:ideaIU-14.1.4
测试环境:win7
protoc-2.6.1下载地址:https://github.com/google/protobuf/releases/download/v2.6.1/protoc-2.6.1-win32.zip
建立maven工程ProtobufDemo,在pom.xml配置文件添加必要的依赖:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>ProtobufDemo</groupId> <artifactId>ProtobufDemo</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java</artifactId> <version>2.6.1</version> </dependency> </dependencies> </project>
根据 Protobuf 的语法规范编写脚本文件 addressbook.proto:
option java_package = "com.mangocool.protobuf"; option java_outer_classname = "AddressBookProtos"; 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; }
java_package:生成proto文件的包路径。
java_outer_classname:生成proto文件的名字。
message:可以看作是Java语言中的javaBean。
option:可选项。
required:必选项。
repeated:可重复项。
通过Protobuf编译工具生成对应proto文件:
protoc -I=$资源路径 --java_out=$生成proto文件路径 $资源路径/addressbook.proto我的命令:
protoc.exe -I=D:\ProtobufDemo\src\main\resources --java_out=D:\ProtobufDemo\src\main\java D:\ProtobufDemo\src\main\resources\addressbook.proto
编译生成的AddressBookProtos.java,这里就不贴了。
接下来我们将Person数据写入磁盘,并从磁盘读出。在classpath下新建文本文件addressbook.txt,用于写入Person和从中读取Person。
写入类WritePerson.java:
package com.mangocool.protobuf; /** * Created by MANGOCOOL on 2015/9/16. */ import com.mangocool.protobuf.AddressBookProtos.AddressBook; import com.mangocool.protobuf.AddressBookProtos.Person; import java.io.*; class WritePerson { static String path = "addressbook.txt"; // 通过用户的输入来添加Person 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())); 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); } return person.build(); } // 读取本地文件addressBook,添加person,最终再写入本地文件addressBook public static void main(String[] args) throws Exception { AddressBook.Builder addressBook = AddressBook.newBuilder(); File file = new File(path); // 读取本地存在的addressBook try { addressBook.mergeFrom(new FileInputStream(file)); } catch (FileNotFoundException e) { System.out.println(args[0] + ": File not found. Creating a new file."); } // 手动添加 addressBook.addPerson( PromptForAddress(new BufferedReader(new InputStreamReader(System.in)), System.out)); // 程序添加 Person.PhoneNumber.Builder phoneNum = Person.PhoneNumber.newBuilder().setNumber("22222222").setType(Person.PhoneType.WORK); Person.Builder person = Person.newBuilder().setName("李四").setId(002).setEmail("002@qq.com").addPhone(phoneNum); addressBook.addPerson(person); // 写入本地文件 FileOutputStream output = new FileOutputStream(file); addressBook.build().writeTo(output); output.close(); } }读取类ReadPerson.java:
package com.mangocool.protobuf; /** * Created by MANGOCOOL on 2015/9/16. */ import com.mangocool.protobuf.AddressBookProtos.AddressBook; import com.mangocool.protobuf.AddressBookProtos.Person; import java.io.File; import java.io.FileInputStream; class ReadPerson { static String path = "addressbook.txt"; // 遍历AddressBook中的所有的person并打印 static void Print(AddressBook addressBook) { for (Person person: addressBook.getPersonList()) { System.out.println("Person ID: " + person.getId()); System.out.println(" Name: " + person.getName()); if (person.hasEmail()) { System.out.println(" E-mail address: " + person.getEmail()); } for (Person.PhoneNumber phoneNumber : person.getPhoneList()) { 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()); } } } public static void main(String[] args) throws Exception { File file = new File(path); // 读取本地文件 AddressBook addressBook = AddressBook.parseFrom(new FileInputStream(file)); // 打印 Print(addressBook); } }代码准备就绪,运行试试:
运行WritePerson.java,并根据提示输入,控制台显示:
Enter person ID: 001 Enter name: 张三 Enter email address (blank for none): 001@qq.com Enter a phone number (or leave blank to finish): 11111111 Is this a mobile, home, or work phone? mobile Enter a phone number (or leave blank to finish):运行ReadPerson.java,读取addressbook.txt中由WritePerson写入的信息:
Person ID: 1 Name: 张三 E-mail address: 001@qq.com Mobile phone #: 11111111 Person ID: 2 Name: 李四 E-mail address: 002@qq.com Work phone #: 22222222
本文对于数据只做了简单的处理,从本地文件做读取,旨意在了解和入门Protobuf。
如需结合其他业务稍加修改即可,如将磁盘替换成网络socket,就可以实现基于网络的数据交换任务了。
到此本文就已结束,有不对或是不完善地方请多多指正以及多多谅解!
参考文章:https://developers.google.com/protocol-buffers/docs/javatutorial
标签: Google Protobuf Java 数据格式 Demo
分享:
崇尚极简,热爱技术,喜欢唱歌,热衷旅行,爱好电子产品的一介码农。
联系QQ:58742094
联系电话:
工作邮箱:
当你的才华还撑不起你的野心的时候,你就应该静下心来学习,永不止步!
人生之旅历途甚长,所争决不在一年半月,万不可因此着急失望,招精神之萎葸。
Copyright 2015- 芒果酷(mangocool.com) All rights reserved. 湘ICP备14019394号
免责声明:本网站部分文章转载其他媒体,意在为公众提供免费服务。如有信息侵犯了您的权益,可与本网站联系,本网站将尽快予以撤除。