[protocol buffers]java解析protoBuf custom option自定义扩展文件具体方法(一)

2014-11-24 03:21:35 · 作者: · 浏览: 5

一、前言

  由于需要解析自定义扩展,获取对应的信息,方便以后扩展,需要解析,上网找了很久木有找到解决办法,而且官方的文档(https://developers.google.com/protocol-buffers/docs/reference/java/index),于是自己在debug模式下一步一步找到解决办法,记录并分享如下。

 

二、具体解决办法

  1)首先需要生成对应的desc文件,这里包含了要解析的所有内容。

  2)然后根据java相关API解析得到具体的自己所需信息。

  闲话少叙,具体代码如下,代码注释的比较清楚:

package com.test.proto;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.protobuf.ByteString;
import com.google.protobuf.DescriptorProtos.DescriptorProto;
import com.google.protobuf.DescriptorProtos.FieldDescriptorProto;
import com.google.protobuf.DescriptorProtos.FileDescriptorProto;
import com.google.protobuf.DescriptorProtos.FileDescriptorSet;
import com.google.protobuf.UnknownFieldSet;

public class ParseProto {
	public final String PROTOC_DIR = System.getProperty(user.dir) + /protoc/protoc.exe ;	// protoc.exe所在文件夹
	public final String PROTO_FILE_DIR = System.getProperty(user.dir) + /protoFile/;	// protoc.exe所在文件夹
	
	/**
	 * 获取自定义扩展的proto信息
	 * @param extendDescFileDir 自定义的扩展文件对应的desc文件路径,如options.desc
	 * @return
	 * @throws Exception
	 */
	public Map
  
    getExtendInfo(String extendDescFileDir) throws Exception {
		Map
   
     result = new HashMap<>(); // 解析desc文件,获取proto文件中的自己扩展 FileDescriptorSet fdSet = FileDescriptorSet.parseFrom(new FileInputStream(extendDescFileDir)); List
    
      fs = fdSet.getFileList(); for(FileDescriptorProto fdp : fs) { // 获取自定义的extend扩展中的name->value List
     
       as = fdp.getExtensionList(); for(FieldDescriptorProto a : as) { result.put(a.getName(), a.getNumber()); } } return result; } /** * 根据proto文件获取其中的message信息 * @return * @throws Exception */ public Map
      
        getMsgInfo(String descFileDir) throws Exception { Map
       
         result = new HashMap
        
         (); // 根据得到的desc文件 FileDescriptorSet fdSet = FileDescriptorSet.parseFrom(new FileInputStream(descFileDir)); for(FileDescriptorProto fdp : fdSet.getFileList()) { // 遍历获取各message信息 for( DescriptorProto dp : fdp.getMessageTypeList()) { String msgName = dp.getName(); // message名称 String value = ; UnknownFieldSet uf = dp.getOptions().getUnknownFields(); for (Map.Entry
         
           entry : uf.asMap().entrySet()) { UnknownFieldSet.Field val = entry.getValue(); value = val.getLengthDelimitedList().get(0).toStringUtf8(); } // 如果存在msgId则记录结果 if(!uf.asMap().isEmpty()) { result.put(msgName, value); } } } return result; } /** * 生成proto文件描述信息desc * @param protoName * @return * @throws Exception */ public String genProtoDesc(String protoName) throws Exception{ // 目标文件名 String descFileDir = this.PROTO_FILE_DIR + protoName.replaceAll(.proto, .desc); // 命令:protoc -I=$SRC_DIR descriptor_set_out=$DST_DIR/***.desc $SRC_DIR/***.proto StringBuffer cmd = new StringBuffer(); cmd.append(cmd /c ); cmd.append(PROTOC_DIR); cmd.append(-I= + this.PROTO_FILE_DIR).append( --descriptor_set_out= + descFileDir).append( ).append(this.PROTO_FILE_DIR + protoName); String failMsg = 生成desc文件命令执行失败!; execCommand(cmd.toString(), 生成desc描述信息文件, failMsg); return descFileDir; } /** * 执行cmd控制台命令 * @param cmd 完整命令语句 * @param failMsg 失败时提示语句 * @throws Exception */ private void execCommand(String cmd, String execMsg, String failMsg) throws Exception { // 执行系统命令 System.out.println(=== + execMsg + =