一、前言
由于需要解析自定义扩展,获取对应的信息,方便以后扩展,需要解析,上网找了很久木有找到解决办法,而且官方的文档(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 + =