C# 使用protobuf CodedInputStream读取字节[]
在下面的代码中,我想在c#中使用预定义的protobuf消息。我发现我能够编写并使用该方法获取已创建的方法,并生成一个C# 使用protobuf CodedInputStream读取字节[],c#,protocol-buffers,C#,Protocol Buffers,在下面的代码中,我想在c#中使用预定义的protobuf消息。我发现我能够编写并使用该方法获取已创建的方法,并生成一个字节[]: ContainerMessage containerMessage = new ContainerMessage(); containerMessage.Type = CommandType.Connect; containerMessage.Connect = new Connect(); containerMessage.Connect.ClientNam
字节[]
:
ContainerMessage containerMessage = new ContainerMessage();
containerMessage.Type = CommandType.Connect;
containerMessage.Connect = new Connect();
containerMessage.Connect.ClientName = "TemporaryClientName";
byte[] stream = new byte[containerMessage.CalculateSize()];
using (Google.Protobuf.CodedOutputStream outstream = new Google.Protobuf.CodedOutputStream(stream))
{
containerMessage.WriteTo(outstream);
}
这可以按预期工作,我可以检查消息,值与字节[]
中的值一样。但是如果我尝试反序列化我刚刚创建的这个简单的字节[]
:
using (Google.Protobuf.CodedInputStream instream = new Google.Protobuf.CodedInputStream(stream))
{
instream.ReadMessage(containerMessage);
}
它失败于:
Google.Protobuf.dll中发生类型为“Google.Protobuf.InvalidProtocolBufferException”的未处理异常
附加信息:协议消息包含无效标记(零)
这种从字节[]反序列化的方法对protobuf正确吗?
Protobuf的定义是:
message ContainerMessage {
CommandType type = 1;
bool commandSuccess = 2;
oneof message {
Connect connect = 3;
}
}
enum CommandType {
START = 0;
CONNECT = 2;
}
message Connect {
string ClientName = 1;
uint32 PushPullPort = 2;
}
并使用命令行生成CS文件:
protoc.exe -I=%CD% --csharp_out=..\GeneratedCsMessaging\ Connect.proto
codedOutStream
和CodedInputStream
主要用于编译的原型类。声明并提到,如果要手动编写代码调用这两个类中的任何一个,则需要在每个值之前使用它们的WriteTag
方法
但是,由于您希望使用Google Protobuf对任何System.IO.Stream进行序列化和解析,因此将按照预期完成此工作。这在本手册的解析和序列化部分中有很好的文档记录和描述。这对于快速掌握Google Protobuf的窍门非常有帮助。您可以看到MemoryStream
用于序列化对象,而Parse.ParseFrom
方法可用于从序列化数据中解析对象
正如你在使用Google.Protobuf对你的问题的评论中提到的
是能够使用GoogleProtobuf功能的重要部分
编辑:在您的案例中,示例用法可能如下所示
byte[] serializedBytes;
ContainerMessage containerMessage = new ContainerMessage()
{
Connect = new Connect()
{
ClientName = "TemporaryClientName",
},
Type = CommandType.Connect,
};
using( MemoryStream stream = new MemoryStream())
{
containerMessage.WriteTo(stream);
serializedBytes = stream.ToArray();
}
ContainerMessage parsedCopy = ContainerMessage.Parser.ParseFrom(serializedBytes);
您是否打算使用CodedOutput和CodedInputStream来反对解析和序列化部分中建议的任何System.IO.Stream?在MemoryStream中,使用CodedInputStream而不是CodedInputStream,反序列化是通过使用Parser.ParseFrom()完成的,Parser.ParseFrom()可用于每个已编译的Protobuf消息。我从未使用CodeDoutStream来序列化消息,但正如中所述,建议使用
WriteTag
方法。这可能解释了即将发生的错误,因为您的标记无效。由于CodedInputStream和CodeDoutpStream都声明“这个类通常由生成的代码使用”,我认为这两个类通常都不打算在生成的类之外使用。我无法建议如何准确地使用CodeDoutpStream
(我的经验是使用protobuf net,您只需调用Serializer.Serialize即可)(stream,obj)
,但您可以在此处轻松检查字节[]
数据是否有效:(您还可以使用从您的模式为protobuf net或Google版本快速生成C,例如:)@Neele,我的问题本质上是两件事。1.我没有rtfm:(2.我没有使用Google.Protobuf;,所以我不明白你可以直接将MemoryStream传递给Google Protobuf。如果你添加你的答案并包含此内容,我将接受。很好。要完全完成此操作,你应该添加一个示例,说明我的代码应该与内存流一起使用。如果你不这样做,我可以。@FantasticMrFox,我刚刚现在补充说:)