V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
amiwrong123
V2EX  ›  程序员

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

  •  1
     
  •   amiwrong123 · 2020-03-07 16:15:38 +08:00 · 4007 次点击
    这是一个创建于 1753 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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);
    

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

    19 条回复    2020-03-09 10:41:11 +08:00
    lixia625
        1
    lixia625  
       2020-03-07 17:17:04 +08:00
    0 是 int32 的默认值,protobuf 对于默认值就不传了(为了效率)
    sikong31
        2
    sikong31  
       2020-03-07 19:28:17 +08:00
    JAVA 和 C++都打个断点,看看编码后的字节一样不一样
    不一样在考虑考虑 protobuf 版本的问题
    wanglufei
        3
    wanglufei  
       2020-03-07 20:30:23 +08:00 via Android
    看下 protobuf 的数据格式 跟下源码
    Sasasu
        4
    Sasasu  
       2020-03-07 20:42:03 +08:00
    最简单的办法是给 repeated packed=true 看看
    会改变序列化方式 java 和 c++ 都需要重新编译
    controller
        5
    controller  
       2020-03-07 22:33:08 +08:00 via Android
    golang protobuf 生成的代码默认加上了 omotempty 的 tag,要么你改下他的源码,要么传字符串
    controller
        6
    controller  
       2020-03-07 22:33:29 +08:00 via Android
    omit
    turi
        7
    turi  
       2020-03-07 22:39:36 +08:00
    自己看字节流吧,反正 protobuf int 字段解析很简单,看看到底是哪个地方接错了
    amiwrong123
        8
    amiwrong123  
    OP
       2020-03-07 23:52:03 +08:00   ❤️ 1
    @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
        9
    coer  
       2020-03-08 01:07:08 +08:00 via Android
    有的字节不是在 unicode 上找不到对应字符,然后被替换成 0xfffd,随便什么字节转字符不会出错吗,还是我记错了...
    terryching
        10
    terryching  
       2020-03-08 08:07:02 +08:00 via Android
    你们跨平台传都不序列化的吗
    laminux29
        11
    laminux29  
       2020-03-08 08:58:50 +08:00
    @amiwrong123

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

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

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

    但是呢,好像是一旦传到了 C++层后,接受到字符串就不对。而我在 C++层解析后,会丢掉字节数组最后的 0,好像是因为 c++的字符串最后是以'\0'结尾的,所以会丢掉最后的 0。
    coer
        19
    coer  
       2020-03-09 10:41:11 +08:00
    @amiwrong123 你用 random 生成 bytes 多试几次吧,如果是默认的 uncoded 字符集,不说内容了,长度都可能不一样
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1318 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 17:30 · PVG 01:30 · LAX 09:30 · JFK 12:30
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.