@linux1s1s
2016-04-28T10:17:18.000000Z
字数 2995
阅读 2970
Java 2016-04
Protocol Buffers(简称protobuf)是谷歌的一项技术,用于将结构化的数据序列化、反序列化,经常用于网络传输。
这货实际上类似于XML生成和解析,但protobuf的效率高于XML,不过protobuf生成的是字节码,可读性比XML差。类似的还有json、Java的Serializable等。
详细了解可以参考Protocol Buffers,接下类将介绍一些基本的使用步骤。
首先通读Protocol Buffers,了解.proto文件的基本格式和写法,下载官方给我们准备的工具,通过该工具可以将.proto文件直接生成需要的代码源文件(比如Java/C/C++/Python等等),接下来直接将该源文件放到工程目录中,编写相应的序列化和反序列化等,这样就完成了整个流程,下面给出简单的实现步骤。
time.proto
option java_package = "com.test.app.pb.common";option java_outer_classname = "TimeProto";message Time {optional int32 id = 1;optional int32 startTime = 2;optional int32 endTime = 3;optional int64 systemTime = 4;optional string countDownTip = 5;optional int32 sEffectiveTime = 6;optional int32 eEffectiveTime = 7;optional string startTip = 8;optional string endTip = 9;}
上面的1、2、3、4是unique numbered tag,是一个唯一标识。这也是整个编码中的亮点,想一探究竟的可以继续往下看。
protoc工具使用的一般格式是:
protoc -I=$SRC_DIR --java_out=$DST_DIR $SRC_DIR/xxx.protoprotoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/xxx.proto
其中SRC_DIR是proto文件所在的目录,DST_DIR是编译proto文件后生成的结构体处理文件的目录
之后会生成对结构体time.proto中描述的各字段做序列化反序列化的类。
工具命令如下:
生成的java代码

将上面生成的代码加入到工程中去,再将Jar包导入工程中,或者添加如下Maver依赖
<dependency><groupId>com.google.protobuf</groupId><artifactId>protobuf-java</artifactId><version>2.6.1</version></dependency>
接下来写测试代码
TimeProto.Time.Builder timeBuilder = TimeProto.Time.newBuilder();timeBuilder.setEEffectiveTime(20160428).setEndTime(20160429).setEndTip("End").setSEffectiveTime(20160428).setStartTime(20160426).setStartTip("Start").setSystemTime(20160428);TimeProto.Time time = timeBuilder.build();ByteArrayOutputStream output = new ByteArrayOutputStream();try {time.writeTo(output);} catch (IOException e) {e.printStackTrace();}
try {HttpClient httpClient = new DefaultHttpClient();url = NetworkUtils.getCompleteUrl(url, getParams);HttpGet request = new HttpGet(url);HttpResponse response = httpClient.execute(request);ByteArrayBuffer buffer = new ByteArrayBuffer(32 * 1024);InputStream in = null;try {HttpEntity entity = response.getEntity();if (entity == null) {} else {in = response.getEntity().getContent();}int temp;byte[] bytes = new byte[8096];while ((temp = in.read(bytes)) != -1) {buffer.append(bytes, 0, temp);}} catch (SocketTimeoutException e) {throw new HttpException(HttpException.MSG_NETWORK_ERROR, e);} catch (IOException e) {throw new HttpException(HttpException.MSG_NETWORK_ERROR, e);} finally {if (in != null) {try {in.close();} catch (IOException e) {e.printStackTrace();}}}byte[] result = buffer.toByteArray();try {TimeProto.Time timeResp = TimeProto.Time.parseFrom(result);} catch (InvalidProtocolBufferException e) {e.printStackTrace();}} catch (SocketTimeoutException e) {throw new HttpException(HttpException.MSG_NETWORK_ERROR, e);} catch (IllegalStateException e) {throw new HttpException(HttpException.MSG_NETWORK_ERROR, e);} catch (IOException e) {throw new HttpException(HttpException.MSG_NETWORK_ERROR, e);}
关键的逻辑在L33到L35行,拿到字符数组以后直接parse出来。
参考文档:
Protocol Buffers 官方文档
Java使用Protocol Buffers入门四步骤 如何使用
google protobuf源码分析1源码分析
Protocol Buffer技术详解(Java实例) 如何使用
玩转Protocol Buffers 如何使用
Google Protocol Buffer 的使用和原理 原理和使用
Why Protocol Buffer So Fast? ----protobuf编码详解 原理和使用
Protocol Buffers编码详解,例子,图解 原理和使用
