我正在尝试从外部源获取负载描述符。 当使用没有导入的生成文件时,它没有问题,但是当原型具有导入,然后在构建FileDescriptor时,我得到DescriptorValidationException:
无法解析描述符./descriptors/test.dsc com.google.protobuf.Descriptors $ DescriptorValidationException:AccessRequest.date_from:“。google.protobuf.Timestamp”未定义。
我用来获取* .dsc文件的原始文件:
syntax = "proto3";
import "google/protobuf/timestamp.proto";
message AccessRequest {
int64 cabinet_id = 1;
google.protobuf.Timestamp date_from = 2;
google.protobuf.Timestamp date_to = 3;
}
我用来获取* .dsc的命令:
protoc --include_imports --proto_path=src/main/proto/ --descriptor_set_out=descriptors/test.dsc src/main/proto/test.proto
我要加载* .dsc文件的代码:
try (final InputStream stream = Files.newInputStream(path)) {
final FileDescriptorSet fds = FileDescriptorSet.parseFrom(stream);
final TypeRegistry.Builder builder = TypeRegistry.newBuilder();
for (final FileDescriptorProto fdp : fds.getFileList()) {
final FileDescriptor fd = FileDescriptor.buildFrom(fdp, new FileDescriptor[]{});
builder.add(fd.getMessageTypes());
globalBuilder.add(fd.getMessageTypes());
}
return new Queue(base, builder.build());
}
答案 0 :(得分:0)
FileDescriptor.buildFrom(fdp, new FileDescriptor[]{})
是关键。
您应该递归地构建依赖关系原型proto(import),并使用结果替换第二个参数。
给我我的代码以供参考
private FileDescriptor buildFileDescriptor(FileDescriptorProto currentFileProto,
Map<String, FileDescriptorProto> fileProtoCache) {
List<FileDescriptor> dependencyFileDescriptorList = new ArrayList<>();
currentFileProto.getDependencyList().forEach(dependencyStr -> {
FileDescriptorProto dependencyFileProto = fileProtoCache.get(dependencyStr);
FileDescriptor dependencyFileDescriptor = buildFileDescriptor(dependencyFileProto, fileProtoCache);
dependencyFileDescriptorList.add(dependencyFileDescriptor);
});
try {
return FileDescriptor.buildFrom(currentFileProto, dependencyFileDescriptorList.toArray(new FileDescriptor[0]));
} catch (DescriptorValidationException e) {
throw new IllegalStateException("FileDescriptor build fail!", e);
}
}
答案 1 :(得分:0)
我知道已经很晚了,但是如果有人想用导入来解析.desc文件,这似乎对我有用:
'''
class Node{
int data;
Node left, right;
int height;
Node(int d){
this.data = d;
this.left = this.right = null;
this.height = 1;
}
Node(){
this.left = this.right = null;
}
}
class MedianFinder {
static Node root;
MedianFinder(){
root = new Node();
}
public void addNum(int num) {
insert(root, num);
}
public static Node insert(Node root, int num){
if(root == null)
return (new Node(num));
if(root.data < num){
root.right = insert(root.right, num);
}
else if(root.data > num)
root.left = insert(root.left, num);
root.height = max(height(root.left) , height(root.right)) + 1;
int balance = get_balance(root);
// if left left
if(balance > 2 && num < root.left.data){
return rightRotation(root);
}
// left right case
if(balance > 2 && num > root.left.data){
leftRotation(root.left);
return rightRotation(root);
}
// right right case
if(balance < -1 && num > root.right.data)
return leftRotation(root);
// right left case
if(balance < -1 && num < root.right.data){
rightRotation(root.right);
return leftRotation(root);
}
return root;
}
public static Node rightRotation(Node node){
Node temp = node.left;
Node tempright = temp.right;
temp.right = node;
node.left = tempright;
node.height = max(height(node.left), height(node.right)) + 1;
temp.height = max(height(temp.left), height(temp.right)) + 1;
return temp;
}
public static Node leftRotation(Node node){
Node temp = node.right;
Node templeft = temp.left;
temp.left = node;
node.right = templeft;
node.height = max(height(node.left), height(node.right)) + 1;
temp.height = max(height(temp.left), height(temp.right)) + 1;
return temp;
}
public static int get_balance(Node node){
if(node == null)
return 0;
return height(node.left) - height(node.right);
}
public static int height(Node node){
if(node == null)
return 0;
return node.height;
}
public static int max(int a, int b){
return a>b?a:b;
}
public double findMedian() {
if(height(root.left) == height(root.right))
return root.data;
return (root.data + root.right.data) / 2;
}
public static int count(Node node){
if(node == null)
return 0;
return 1 + count(node.left) + count(node.right);
}
}
/**
* Your MedianFinder object will be instantiated and called as such:
* MedianFinder obj = new MedianFinder();
* obj.addNum(num);
* double param_2 = obj.findMedian();
*/
'''