当前位置: 首页 > 知识库问答 >
问题:

在Java中使用proto3时,对象中的长值未正确序列化和反序列化

东方新霁
2023-03-14

我试图序列化和反序列化一个对象在java中使用Prop3

option java_multiple_files = true;
option java_package = "com.project.dataModel";
option java_outer_classname = "FlowProto";


// The request message containing the user's name.
message Flow {
    string subscriberIMSEI = 1;
    string destinationIP = 2;
    uint64 txBytes = 3;
    uint64 rxBytes = 4;
    uint64 txPkts = 5;
    uint64 rxPkts = 6;
    uint64 startTimeInMillis = 7;
    uint64 endTimeInMillis = 8;
    string asnNumber = 9;
    string asnName = 10;
    string asnCountryCode = 11;

}

下面是我在java中的序列化和反序列化的样子

public class Test {

    public static void main(String[] args) throws Exception {

        Flow flow =
                Flow.newBuilder().setAsnName("abc")
                        .setEndTimeInMillis(123456789L)
                        .setStartTimeInMillis(123456789L)
                .setDestinationIP("1.1.1.1")
                .setTxBytes(1L)
                .setRxBytes(1L)
                .setTxPkts(1L)
                .setRxPkts(1L)
                .setAsnName("blah")
                .setAsnCountryCode("blah")
                .build();

        byte[] flowByteArray = flow.toByteArray();

        String flowString = flow.toByteString().toStringUtf8();

        System.out.println("Parsed from ByteArray:" + Flow.parseFrom(flowByteArray).getEndTimeInMillis());
        System.out.println("Parsed from ByteString:" + Flow.parseFrom(ByteString.copyFromUtf8(flowString))
                .getEndTimeInMillis());
    }
}

我的输出如下

Parsed from ByteArray:123456789
Parsed from ByteString:-4791902657223630865

当我试图使用ByteString和utf-8路由进行序列化和反序列化时,我哪里出错了?

谢谢!

共有1个答案

诸俊才
2023-03-14

您看到问题的原因是因为您的序列化字节数组被损坏。发生这种情况是因为UTF-8是一个可变长度编码,转换为UTF-8字符串会改变原始数组中的字节。当您执行flow.toByteString()。toStringUtf8()时,原始字节串中的一个字节可能会转换为具有不同值的三个新字节。然后当您执行ByteString.copyFromUtf8(流字符串)时,字节更改不会撤销,因为该行代码实际上只是检索转换后的UTF-8字节,而不是您输入的原始字节。

下面是一个小测试,它说明了您看到的问题

@Test
public void byteConsistency() {
  byte[] vals = new byte[] {0, 110, -1};
  ByteString original = ByteString.copyFrom(vals);
  ByteString newString = ByteString.copyFromUtf8(original.toStringUtf8());

  for (int index = 0; index < newString.size(); index++) {
    System.out.println(newString.byteAt(index));
  }
}

你会期望这个代码输出

0
110
-1

但它实际上输出

0
110
-17
-65
-67

这是因为UTF-8可能要求将-1(0xFF)字节编码为三个字节[-17、-65、-67]。

总之,在处理原型时,不要将序列化的对象转换成UTF-8字符串。只使用原始字节进行序列化和反序列化。如果您尝试转换成UTF-8字符串,序列化的字节将被损坏,您将无法对它们进行反序列化。

 类似资料:
  • 我需要一个自定义反序列化器来在复杂的POJO中转换字符串。反序列化工作直到使用反序列化器:特别是使用自定义反序列化器时,我的对象的非对象属性不会序列化。 我有一个restful Web服务,它有一个pojo作为参数。 所以我的类PreentivoWs需要一个方法。这里是类定义: 在jsonObject中,我有一个枚举定义为 但此对象需要转换反序列化程序: 并在财产上标注: fromString方法

  • 我试图序列化一个对象数组,并将其写入一个名为address.ser的文件,然后从该文件中读取,反序列化对象数组并显示其属性。我尝试一次序列化整个arrayList(读取时在单个会话中反序列化它),也尝试一个接一个地序列化对象数组的每个对象(读取时一个接一个地反序列化它)。问题是,当从address.ser文件读回来时,我只得到最后一个被写入的对象的数据,而不是其他的。 以下是代码片段: 这是用于将

  • 本文向大家介绍java对象的序列化和反序列化,包括了java对象的序列化和反序列化的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了java对象的序列化和反序列化,供大家参考,具体内容如下 1. 什么是序列化        将对象转换为字节流保存起来,比如保存到文件里,并在以后还原这个对象,这种机制叫做对象序列化。(补充一句:把对象保存到永久存储设备上称为持久化) 2. 怎么实现序列化

  • 上下文:我们使用Activiti作为流程引擎,使用Activiti-Rest作为应用程序的接口。由于这个问题与返回由Java序列化的对象的REST服务有关,所以我没有将其添加到标题中。 场景:我们有一个JBoss Wildfly实例,它包含一个EAR和一个包含类“ProcessContext”的模块(为了参考,我们将其称为X)。Activiti在这个EAR中运行,ServiceTasks(从进程中

  • 错误: java.lang.ClassNotFoundException:testprocedure.tp$3在java.net.URLClassLoader$1上运行(未知源)在java.net.URLClassLoader上运行(未知源)在java.security.accessController.doprivileged(本机方法)在java.net.URLClassLoader.find

  • 以下代码导致此异常: 所以问题是:如何在GSON序列化和反序列化的泛型HashMap中获得正确的实例?