protobuf 的 repeated 字段在遇到 0 的时候,就很奇怪啊

2020-03-07 16:15:38 +08:00
 amiwrong123
message mess {
    optional int32  No = 1;
    repeated int32  IDs = 2;
}

然后我是从 java 层传到 c++层,这个 IDs 字段里,只有没有加入 0 这个数,c++层收到后都是正常的,但只要加入了 0,c++层解析出来的就不对了。

比如: IDs 字段为 [ 64,65,33,22,0 ] ,C++层再解析出来,就只有 [ 64,65,33,22 ] 了.

IDs 字段为 [ 64,65,33,22,0,22 ] ,C++层再解析出来,就变成 [ 64,65,33,22,64 ] 了

总之,只要有 0 在里面,就会很奇怪。

java 层是这么做的,通过 HIDl 接口发给 c++层。

mess proto = new mess();
proto.No = 1;
proto.IDs = new int[] {64,65,33,22,0};
String sendString = new String(mess.toByteArray(proto));

c++层是这么解析的:

std::string strProtoBuf = Obj->getProtoInfo();  //反正这里得到了,传来的字符串
mess proto;
mess.ParseFromString(strProtoBuf);

求助各位大佬,该怎么解啊

3979 次点击
所在节点    程序员
19 条回复
lixia625
2020-03-07 17:17:04 +08:00
0 是 int32 的默认值,protobuf 对于默认值就不传了(为了效率)
sikong31
2020-03-07 19:28:17 +08:00
JAVA 和 C++都打个断点,看看编码后的字节一样不一样
不一样在考虑考虑 protobuf 版本的问题
wanglufei
2020-03-07 20:30:23 +08:00
看下 protobuf 的数据格式 跟下源码
Sasasu
2020-03-07 20:42:03 +08:00
最简单的办法是给 repeated packed=true 看看
会改变序列化方式 java 和 c++ 都需要重新编译
controller
2020-03-07 22:33:08 +08:00
golang protobuf 生成的代码默认加上了 omotempty 的 tag,要么你改下他的源码,要么传字符串
controller
2020-03-07 22:33:29 +08:00
omit
turi
2020-03-07 22:39:36 +08:00
自己看字节流吧,反正 protobuf int 字段解析很简单,看看到底是哪个地方接错了
amiwrong123
2020-03-07 23:52:03 +08:00
@lixia625
@sikong31
@wanglufei
@Sasasu
@controller
@turi

真相大白了,是我不该用 string 作为载体的。
比如我在 java 层执行了 mess.toByteArray(proto),如果 IDs 字段为 [ 64,65,33,22,0 ] 转换成的字节数组为 [8 1 16 64 16 3 16 65 16 7 16 67 16 36 16 0 ] ,再执行 new String()就丢掉最后面那个 0.

然后我加接口了,让接口 直接传递那个字节数组就好了。

哎,怪自己考虑不周。
coer
2020-03-08 01:07:08 +08:00
有的字节不是在 unicode 上找不到对应字符,然后被替换成 0xfffd,随便什么字节转字符不会出错吗,还是我记错了...
terryching
2020-03-08 08:07:02 +08:00
你们跨平台传都不序列化的吗
laminux29
2020-03-08 08:58:50 +08:00
@amiwrong123

这不是你考虑不周的问题,这明明就是 api 的问题。包装一下就把数据给丢了,这问题太严重了。
livepps
2020-03-08 09:26:09 +08:00
二进制转字符串的都会我也遇到过,跟你的不大一样,是浮点数有问题,后来就不转了 string 了,用二进制 api 收发数据
sikong31
2020-03-08 10:09:36 +08:00
@laminux29 这和 protobuf 的 api 没有关系,是 java string 的 api 的对 byte 数组行为的。错的是不应该转成 string
laminux29
2020-03-08 10:38:28 +08:00
@sikong31

1.Java 的 byte 数组转 String 的 API,处理上没问题。

2.byte 数组转 string,这是个很常见的需求,没有不应该一说。
coer
2020-03-08 17:01:18 +08:00
@laminux29 随便什么 bytes 数组转 string 保存要指定字符集是 iso-8895-1,默认的如果是 unicode 是不行的吧
laminux29
2020-03-08 17:09:16 +08:00
@coer 试试总比猜测好,对不?
coer
2020-03-08 17:23:20 +08:00
我是说 new string(byte[]).getBytes()出来的字节数组和原字节数组可能是不一样的
amiwrong123
2020-03-08 22:06:42 +08:00
@coer
你说的这个,我试了一下,在 java 的话,两个字节数组是一样的。

但是呢,好像是一旦传到了 C++层后,接受到字符串就不对。而我在 C++层解析后,会丢掉字节数组最后的 0,好像是因为 c++的字符串最后是以'\0'结尾的,所以会丢掉最后的 0。
coer
2020-03-09 10:41:11 +08:00
@amiwrong123 你用 random 生成 bytes 多试几次吧,如果是默认的 uncoded 字符集,不说内容了,长度都可能不一样

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/650710

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX