一、前言
本文将介绍用java解析.proto文件。
由于protobuffer的java库里面有提供可以直接解析.ptoto文件的相关类,所以并不能像C++那样直接可以解析.proto文件,我google了半天才在网上找到方法,于是便有了这篇博文。(此处需要用到protobuf的jar文件,可以点击此处下载)
二、具体解析方法
不能直接用protobuf提供的库来解析.proto文件,但是可以用它提供的解析的.desc文件来获取.proto文件信息。所以要先调用如下命令生成desc文件:
protoc -I=$SRC_DIR descriptor_set_out=$DST_DIR/***.desc $SRC_DIR/***.proto
然后就可以用FileDescriptorSet这个来解析了,然后获得FileDescriptor,在看官方网上关于protobuf的API就可以得到想要的信息了。具体看如下代码:
package com.test.proto;
import java.io.FileInputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.google.protobuf.DescriptorProtos.FileDescriptorProto;
import com.google.protobuf.DescriptorProtos.FileDescriptorSet;
import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.Descriptors.FileDescriptor;
public class Test {
public static void main(String[] args) throws Exception {
Runtime run = Runtime.getRuntime();
String dir = System.getProperty("user.dir");
String source = dir + "/protoc/";
String cmd = "cmd /c " + source + "protoc.exe -I=" + source + " --descriptor_set_out="+ source +"addressbook.desc "+ source +"addressbook.proto";
System.out.println(cmd);
Process p = run.exec(cmd);
// 如果不正常终止, 则生成desc文件失败
if (p.waitFor() != 0) {
if (p.exitValue() == 1) {//p.exitValue()==0表示正常结束,1:非正常结束
System.err.println("命令执行失败!");
System.exit(1);
}
}
Map<String, String> mapping = new HashMap<String, String>();
FileInputStream fin = new FileInputStream("addressbook.desc");
FileDescriptorSet descriptorSet = FileDescriptorSet.parseFrom(fin);
for (FileDescriptorProto fdp: descriptorSet.getFileList()) {
FileDescriptor fd = FileDescriptor.buildFrom(fdp, new FileDescriptor[]{});
for (Descriptor descriptor : fd.getMessageTypes()) {
String className = fdp.getOptions().getJavaPackage() + "."
+ fdp.getOptions().getJavaOuterClassname() + "$"
+ descriptor.getName();
List<FieldDescriptor> types = descriptor.getFields();
for(FieldDescriptor type : types) {
System.out.println(type.getFullName());
}
System.out.println(descriptor.getFullName() + " -> " + className);
}
}
// Descriptor md = fd.getDescriptorForType();
// byte[] data = null ;
// DynamicMessage m = DynamicMessage.parseFrom(md, data);
}
}
三、结果截图
四、附件(addressbook.proto)
package com.example.tutorial;
option java_package = "com.example.tutorial";
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;
}
(全文完)
注:这个是本人原创的,如需转载,请尊重劳动果实,务必保持 原链接( http://blog.csdn.net/lufeng20/article/details/8736584)
。