Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/362.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 有没有一种不用代码生成就可以编写原型数据的方法?_Java_Reflection_Protocol Buffers - Fatal编程技术网

Java 有没有一种不用代码生成就可以编写原型数据的方法?

Java 有没有一种不用代码生成就可以编写原型数据的方法?,java,reflection,protocol-buffers,Java,Reflection,Protocol Buffers,我想知道是否可以使用google protobuf提供的反射API来序列化消息,而无需生成代码? 协议缓冲区允许我们在解析过程后对消息或Message.Builder对象使用反射。但在我的例子中,我想知道是否可以用字段/值填充这些对象,然后将它们写入文件。codedOutStream 实现这一点的一种方法是了解和如何使用适当的write*()方法编写消息字段 例如,写下以下信息: message MyMessage { int foo = 1; string bar = 2; }

我想知道是否可以使用google protobuf提供的反射API来序列化消息,而无需生成代码?

协议缓冲区允许我们在解析过程后对
消息
Message.Builder
对象使用反射。但在我的例子中,我想知道是否可以用字段/值填充这些对象,然后将它们写入文件。

codedOutStream 实现这一点的一种方法是了解和如何使用适当的
write*()
方法编写消息字段

例如,写下以下信息:

message MyMessage {
    int foo = 1;
    string bar = 2;
}
您可以使用以下代码:

ByteArrayOutputStream baos = new ByteArrayOutputStream();
CodedOutputStream out = CodedOutputStream.newInstance(baos);
out.writeInt32(1, 1);
out.writeString(2, "s");
out.flush();
byte[] rawProtocolBuffer = baos.toByteArray();
动态消息 另一种方法是手工创建描述符,然后使用
DynamicMessage
设置相应的字段,但这比直接使用
codedoutstream
更简单

String messageName = "MyMessage";
FileDescriptorProto fileDescriptorProto = FileDescriptorProto
        .newBuilder()
        .addMessageType(DescriptorProto.newBuilder()
                .setName(messageName)
                .addField(FieldDescriptorProto.newBuilder()
                        .setName("foo")
                        .setNumber(1)
                        .setType(FieldDescriptorProto.Type.TYPE_INT32)
                        .build())
                .addField(FieldDescriptorProto.newBuilder()
                        .setName("bar")
                        .setNumber(2)
                        .setType(FieldDescriptorProto.Type.TYPE_STRING)
                        .build())
                .build())
        .build();

Descriptor messageDescriptor = FileDescriptor
        .buildFrom(fileDescriptorProto, new FileDescriptor[0])
        .findMessageTypeByName(messageName);

DynamicMessage message = DynamicMessage
        .newBuilder(messageDescriptor)
        .setField(messageDescriptor.findFieldByNumber(1), 1)
        .setField(messageDescriptor.findFieldByName("bar"), "s")
        .build();

byte[] rawProtocolBuffer = message.toByteArray();

首先,您需要将proto文件编译成desc文件

protoc --descriptor_set_out=point.desc --include_imports point.proto
然后,使用desc文件对消息进行编码和解码

InputStream input = new FileInputStream("point.desc");
DescriptorProtos.FileDescriptorSet descriptorSet = DescriptorProtos.FileDescriptorSet.parseFrom(input);
DescriptorProtos.FileDescriptorProto fileDescriptorProto = descriptorSet.getFile(0);

Descriptors.Descriptor messageDescriptor = Descriptors.FileDescriptor
        .buildFrom(fileDescriptorProto, new Descriptors.FileDescriptor[0])
        .findMessageTypeByName("Point");


// Encoding
DynamicMessage message = DynamicMessage
        .newBuilder(messageDescriptor)
        .setField(messageDescriptor.findFieldByNumber(1), 10)
        .setField(messageDescriptor.findFieldByNumber(2), 5)
        .setField(messageDescriptor.findFieldByName("label"), "test label")
        .build();

byte[] encodedBytes = message.toByteArray();


// Decoding
DynamicMessage dynamicMessage = DynamicMessage.parseFrom(messageDescriptor, encodedBytes);

int x = (int) dynamicMessage.getField(messageDescriptor.findFieldByName("x"));
int y = (int) dynamicMessage.getField(messageDescriptor.findFieldByName("y"));
String label = (String) dynamicMessage.getField(messageDescriptor.findFieldByName("label"));

你真的需要先创建对象吗?您可以只写
codedOutStream
。或者您可以创建一个
描述符
并使用
动态消息
。事实上,我已经编写了一个工具来为特定的给定对象生成协议缓冲区模式。之后,我想通过使用生成的shema(添加字段和值,即在对象中描述和填充“模式”),填充一个proto对象,然后序列化该对象。
Descriptor
类可以做到吗?
Descriptor
类实际上是一个模式。我将尝试使用它。非常感谢您的快速回答。描述符类是协议缓冲区中内置的proto缓冲区定义。protoc命令可以将.proto转换为协议缓冲区文件,您可以使用描述符类来读取它。