【问题标题】:Object to bytes array in JavaJava中的对象到字节数组
【发布时间】:2022-01-01 06:01:14
【问题描述】:

我正在研究专有的 TCP 协议。该协议发送和接收具有特定字节序列的消息。

我应该遵守这个协议,我不能改变它。 所以我的输入/输出结果是这样的:
\x01\x08\x00\x01\x00\x00\x01\xFF

\x01 - Message type
\x01 - Message type
\x00\x01 - Length
\x00\x00\x01 - Transaction
\xFF - Body

字段的顺序很重要。而且我只想要序列化中字段的值,而不想要类的结构。

我正在开发一个使用此协议的 Java 控制器,我曾想过在特定类中定义消息结构并序列化/反序列化它们,但我很天真。

首先我尝试了 ObjectOutputStream,但是当我只需要特定顺序的值时,它会输出对象的整个结构。

有人已经遇到过这个问题: Java - Object to Fixed Byte Array
并通过专门的 Marshaller 解决。

但我正在寻找更灵活的解决方案。

对于文本序列化和反序列化我发现:
http://jeyben.github.io/fixedformat4j/
带有注释的那个定义了该行的模式。但它输出一个字符串,而不是byte[]。因此 1 的输出类似于“1”,根据编码的不同表示不同,并且通常具有更多字节。

我正在搜索的是给定我的类属性的顺序的东西,它将把每个属性转换成一堆字节(基于内部表示)并将它们附加到byte[]

您知道一些用于此目的的库吗?
还是一种简单的方法来做到这一点,而无需为我的每个实体编写序列化算法?

【问题讨论】:

    标签: java serialization tcp bytebuffer


    【解决方案1】:

    序列化并不容易;从你的问题听起来,你觉得你可以调用一些东西,然后推出紧凑、简单、可版本化、通用的数据,然后你可以把它们放在网络上。您需要解决的是从该句子中删除“just”一词。您将不得不投入一些时间和精力。

    正如您已经发现的那样,Java 的序列化功能有很多缺点。不要用那个。

    有各种序列化程序。流行的是 GSONJackson 之类的东西,它们可以让您将 java 对象序列化为 JSON。这不是特别有效,并且是基于字符串的。这听起来像是关键的缺点,但实际上并非如此,请参见下文。

    您还可以花更多时间指定确切的格式并使用protobuf,它可以让您编写一个非常精简和简单的数据协议(如果您最终想编写一个参与者,那么 protobuf 可用于多种语言以后非java协议)。

    所以,这些都是不错的选择:通过 Jackson 或 GS​​ON 转到 JSON,或者使用 protobuf。

    但是 JSON 是一个字符串。

    您可以使用str.getBytes(StandardCharsets.UTF_8) 轻松地将字符串转换为字节。由于字符集编码的差异,这不会失败(只要您也以相同的方式“解码”:将字节转换为带有new String(theBytes, StandardCharsets.UTF_8) 的字符串。UTF-8 保证在所有JVM;如果不存在,那么您的 JVM 就像缺少 String 类的 JVM 一样损坏 - 无需担心。

    但是 JSON 效率低。

    当然要拉上拉链。您可以简单地包装一个 InputStream 和一个 OutputStream 以便应用 gzip 压缩,这很简单,几乎在每个平台上都可用,而且速度很快(它不是最有效的前沿压缩算法,但通常挤出最后几个字节是不值得的它)- 压缩后的 JSON 通常甚至比精心处理的 protobuf 更有效。

    一个缺点是它“慢”,但在现代硬件上,请注意加密和解密此数据的开销(您显然应该这样做!!)通常涉及多个数量级。现代 CPU 非常、非常快 - 创建 JSON 并将其压缩起来将占用 1% 或更少的 CPU,即使您每秒都发送莎士比亚的作品集。

    如果使用电池运行的 arduino 需要处理这些数据,请使用未压缩、未加密的基于 protobuf 的数据。如果您是 facebook 并且正在编写 whatsapp 协议,那么无需解压缩和解码 JSON 所节省的 IAAS 信用与您仅用于运行服务器的信用相比是微不足道的,但在这种规模上,它值得开发努力。

    在几乎所有其他情况下,只需将 gzip 压缩的 JSON 扔就行了。

    【讨论】:

    • 感谢您的回复。我已经编辑了我的帖子,并举了一个例子,因为它可能不太清楚。字段的顺序很重要。而且我只想要序列化中字段的值,而不想要类的结构。所以我认为我可以排除 Json,即使是以字节为单位解码。
    • 是的,现在你的问题完全不同了。你所说的是编写一个特定的协议。 没有序列化库可以为您执行此操作,您必须手动处理此代码或为此特定协议查找现有库。
    猜你喜欢
    • 1970-01-01
    • 2011-02-19
    • 2015-11-11
    • 2019-05-09
    • 1970-01-01
    • 2010-12-07
    • 1970-01-01
    相关资源
    最近更新 更多