簡體   English   中英

無法從Java中的C ++反序列化protobuf數據

[英]Cannot deserialize protobuf data from C++ in Java

我的問題是用C ++序列化protobuf數據並用Java反序列化數據。 這是我用於dcn給出的提示的代碼:

有了這個,我用C ++創建protobuf數據並將其寫入通過套接字發送的ostream。

Name name;
name.set_name("platzhirsch");

boost::asio::streambuf b;
std::ostream os(&b);

ZeroCopyOutputStream *raw_output = new OstreamOutputStream(&os);
CodedOutputStream *coded_output = new CodedOutputStream(raw_output);

coded_output->WriteLittleEndian32(name.ByteSize());
name.SerializeToCodedStream(coded_output);
socket.send(b);

這是我嘗試解析它的Java端:

NameProtos.Name name = NameProtos.Name.parseDelimitedFrom(socket.getInputStream());
System.out.println(name.newBuilder().build().toString());

但是,我得到了這個例外: com.google.protobuf.UninitializedMessageException:消息缺少必填字段:name

我錯過了什么?


有缺陷的代碼行是: name.newBuilder().build().toString()

這將永遠不會起作用,使用未初始化的名稱字段創建新實例。 無論如何,這里的答案解決了我的其余問題。

最后一件事,我在protobuf郵件列表中被告知:為了刷新CodedOutputStreams,必須刪除對象!

delete coded_output;
delete raw_output;

我不知道你的Java代碼received什么,但你的問題可能是由於一些字符集轉換。 另請注意,protobuf在序列化時不會分隔消息。

因此,您應該使用原始數據來傳輸消息(字節數組或直接(de)從/向流序列化)。 如果您打算發送許多消息,您還應該在發送實際消息之前發送大小。

在Java中,您可以通過parseDelimitedFrom(InputStream)writeDelimitedTo(OutputStream)直接執行此操作。 使用CodedOutputStream就可以在C ++中執行相同的操作

codedOutput.WriteVarint32(protoMessage.ByteSize());
protoMessage.SerializeToCodedStream(&codedOutput);

另見這個更早的線程。

您正在向流寫入兩個內容,一個大小和Name對象,但只是嘗試讀取一個。

作為一般問題:為什么你覺得需要使用CodedInputStream? 引用文檔

通常,這些類僅由協議緩沖庫在內部使用,以便對協議緩沖區進行編碼和解碼。 如果他們希望編寫自定義消息解析或序列化過程,則庫的客戶端只需要知道該類

並強調jtahlborn的評論:為什么小端? Java處理大端值,因此必須在讀取時進行轉換。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM