Protobuf Java 到 C++ 序列化 [二进制]
Protobuf Java To C++ Serialization [Binary]
我有一个程序在 Java 中使用 Protobuf 序列化数据,方法是将二进制数据写入 byte[] 数组,然后将其保存在“.txt”文件中。我在字符串流中的 C++ 端接收到该数据。现在我想用 C++ 解析二进制数据,但是 Protobuf-Parsing-Method "parseFromString()" 不起作用!我的测试消息中的字段未设置。我为此写了一个小测试,我可以给你看一些代码:
Java连载
byte[] s = test.build().toByteArray(); //This is serialized to "C:\test.txt" as binary
C++ 解析:
Test t1; // My Protobuf Message
std::ifstream myFile("C:\test.txt");
std::string s;
myFile >> s;
t1.ParseFromString(s);
std::cout << "Decoded: " << t2.s() << std::endl; // Check if parsing was correct
但它只是 returns: " Decoded: ",好像 t2 是空的,但它不应该是!如何在 C++ 中解析二进制数据?
问题是您在混合调用 API。您正在使用 toByteArray
API 调用进行序列化,并使用 ParseFromString
API 调用进行反序列化。
您可以使用其中一对,但不能混用:
ParseFromString
和 SerializeToString
对
SerializeToArray
和 ParseFromArray
对
我正在编写 C++ 和 python。我附上了我的代码中的以下示例。我想你应该能够从这个例子中理解它是如何工作的。
如果有什么不明确的地方请给我留言。
这是我的 python 连载:
socket.send(request.SerializeToString())
和C++反序列化:
// Deserialize request.
if (request.ParseFromString(protobuf_request) == false) {
throw exception();
}
这是我的 C++ 序列化:
// Serialize response.
assert(response.SerializeToString(&protobuf_response) == true);
和python反序列化:
response.ParseFromString(str(message))
编辑:
我认为你应该使用:
- void writeTo(OutputStream 输出);在
Java
- bool ParseFromIstream(istream* 输入);在
C++
你的问题可能出在这里:
myFile >> s;
>>
运算符读取 text 字符串,由空格分隔。编码的 protobuf 不是文本。可能 ParseFromString()
返回 false 表示它无法解析数据,因为它不完整。
您要做的是读取整个文件。在您的情况下执行此操作的最简单方法是使用 ParseFromIstream(&myFile)
。 (并确保检查它 returns 是真的!)
(另一种选择是检查文件大小,创建该大小的数组,使用 myFile.read(array, size)
,然后使用 ParseFromArray(array, size)
,但这需要做更多的工作来做同样的事情.)
请注意,您可能不应该使用 .txt
作为 protobuf 的文件扩展名,因为该文件不包含文本。
另请注意,令人困惑的是,在 C++ 中,您可以将二进制(非文本)数据放入 std::string
-- 它只是一个字节容器 -- 但在 Java 中,您 不能将二进制数据放在String
中。所以 C++ ParseFromString()
和 SerializeAsString()
处理二进制数据,而 Java toString()
实际上 returns 消息的文本表示(用于调试目的) 不是您要传输的内容。
我有一个程序在 Java 中使用 Protobuf 序列化数据,方法是将二进制数据写入 byte[] 数组,然后将其保存在“.txt”文件中。我在字符串流中的 C++ 端接收到该数据。现在我想用 C++ 解析二进制数据,但是 Protobuf-Parsing-Method "parseFromString()" 不起作用!我的测试消息中的字段未设置。我为此写了一个小测试,我可以给你看一些代码:
Java连载
byte[] s = test.build().toByteArray(); //This is serialized to "C:\test.txt" as binary
C++ 解析:
Test t1; // My Protobuf Message
std::ifstream myFile("C:\test.txt");
std::string s;
myFile >> s;
t1.ParseFromString(s);
std::cout << "Decoded: " << t2.s() << std::endl; // Check if parsing was correct
但它只是 returns: " Decoded: ",好像 t2 是空的,但它不应该是!如何在 C++ 中解析二进制数据?
问题是您在混合调用 API。您正在使用 toByteArray
API 调用进行序列化,并使用 ParseFromString
API 调用进行反序列化。
您可以使用其中一对,但不能混用:
ParseFromString
和SerializeToString
对SerializeToArray
和ParseFromArray
对
我正在编写 C++ 和 python。我附上了我的代码中的以下示例。我想你应该能够从这个例子中理解它是如何工作的。 如果有什么不明确的地方请给我留言。
这是我的 python 连载:
socket.send(request.SerializeToString())
和C++反序列化:
// Deserialize request.
if (request.ParseFromString(protobuf_request) == false) {
throw exception();
}
这是我的 C++ 序列化:
// Serialize response.
assert(response.SerializeToString(&protobuf_response) == true);
和python反序列化:
response.ParseFromString(str(message))
编辑:
我认为你应该使用:
- void writeTo(OutputStream 输出);在
Java
- bool ParseFromIstream(istream* 输入);在
C++
你的问题可能出在这里:
myFile >> s;
>>
运算符读取 text 字符串,由空格分隔。编码的 protobuf 不是文本。可能 ParseFromString()
返回 false 表示它无法解析数据,因为它不完整。
您要做的是读取整个文件。在您的情况下执行此操作的最简单方法是使用 ParseFromIstream(&myFile)
。 (并确保检查它 returns 是真的!)
(另一种选择是检查文件大小,创建该大小的数组,使用 myFile.read(array, size)
,然后使用 ParseFromArray(array, size)
,但这需要做更多的工作来做同样的事情.)
请注意,您可能不应该使用 .txt
作为 protobuf 的文件扩展名,因为该文件不包含文本。
另请注意,令人困惑的是,在 C++ 中,您可以将二进制(非文本)数据放入 std::string
-- 它只是一个字节容器 -- 但在 Java 中,您 不能将二进制数据放在String
中。所以 C++ ParseFromString()
和 SerializeAsString()
处理二进制数据,而 Java toString()
实际上 returns 消息的文本表示(用于调试目的) 不是您要传输的内容。