【问题标题】:Java Custom Serialization and Deserialization with Bit size definitions具有位大小定义的 Java 自定义序列化和反序列化
【发布时间】:2026-01-17 12:45:01
【问题描述】:

问题: 我需要从具有固定数据包格式定义的电子设备实现网络输入阅读器。它有一个页眉、页脚和数据体。数据包中的字段以位为单位定义。

示例: 字段 sequence_number 变量是编号为 8 到 31 的位,而 ack_status 是位 32。如何创建自定义序列化函数,以便可以将 java 对象与从数据包中读取的 byte[] 进行转换?

在 32 位数据包中

StartOfPacketHeader 4bits

CommandCode 4bits

SequenceNumber 23bits

AckStatus 1bit

如何使用 byte[] 构造函数和 toBytes() 方法为这个对象创建一个 Java 包装类。

使用可序列化接口无法控制单个数据的大小。数据大小可能是奇数,例如 3 位或 18 位变量。我无法以位为单位指定变量的长度。

到目前为止我做了什么:

源实际上发送无符号整数,这意味着 Java int 类型无法处理其整个范围。我需要定义所有数据类型,只要处理所有情况。我已经使用 BitSet 类来执行 byte[] 到 Long 的转换,但它太繁琐和令人困惑,因为 bitset 默认将位顺序反转为 Little Endian。

总结:

如何以最有效的方式将我从网络读取的字节[] 转换为我的对象,反之亦然,并为每个字段提供自定义定义?

【问题讨论】:

    标签: java serialization deserialization ethernet


    【解决方案1】:

    您为此使用DataInputStreamDataOutputStream,并在它们下面分别使用BufferedInputStreamBufferedOutputStream 以提高效率。您必须自己编写位字段,但这些类以网络字节顺序提供所有 Java 原语。

    对于您发布的数据包,您需要这样的东西:

    class Packet
    {
        private byte    header;
        private byte    commandCode;
        private int     sequenceNumber;
        private boolean ackStatus;
    
        void    write(DataOutput out) throws IOException
        {
            int wirePacket = header|(commandCode << 4)|(sequenceNumber << 8);
            if (ackStatus)
            {
                wirePacket |= 0x80000000;
            }
            out.writeInt(wirePacket);
        }
    
        static Packet   read(DataInput in) throws IOException
        {
            Packet  packet = new Packet();
            int wirePacket = in.readInt();
            packet.header = (byte)(wirePacket & 0x0f);
            packet.commandCode = (byte)((wirePacket >>> 4) & 0x0f);
            packet.sequenceNumber = (wirePacket >>> 8) & 0x7FFFFF;
            packet.ackStatus = (wirePacket & 0x80000000) != 0;
            return packet;
        }
        // getters and setters. The setters must ensure that the values don't go out of range.
    }
    

    【讨论】:

    • 你能举个例子吗?
    • 我无法调和这两个说法。
    • 我的问题是处理位级序列化,我已经知道如何处理流并执行基本对象到字节的转换
    • 我该如何改进这个问题?
    • 不清楚你需要什么,如果不是这样的话。如何屏蔽和移位?