java - 如何使用 Java 将 INT32 打包到我的 MessagePack 中?

标签 java msgpack

我遇到了一个问题,我需要将 INT32 发送到另一个应用程序,但根据我的阅读,messagepack.putIntmessagepack.putLong 将尝试将其优化为 UINT32,这会给接收应用程序带来问题。

接收应用程序给我错误消息

decode error, skipping message. msgp: attempted to decode type "uint" with method for "int"

我正在使用带有依赖项的 Maven

  <dependency>
   <groupId>org.msgpack</groupId>
   <artifactId>msgpack-core</artifactId>
   <version>0.8.13</version>
</dependency>

其他人也遇到了同样的问题,并表示解决方案如下

好的,所以我们发现了问题,看起来 metricTank 要求将消息对象的 time 属性序列化为 INT32,但是 packInt(或 packLong)总是会尝试将其优化为 metricTank 不喜欢的 UINT32。所以我们必须使用 addPayload 并序列化 MessagePacker.Code.INT32,然后是实际的 4 个字节的 time 属性。

但我不确定该怎么办,也无法联系 OP。

我尝试了以下方法,但不起作用

ByteBuffer buf = ByteBuffer.allocate(1 + Long.BYTES);
buf.put(MessagePack.Code.INT32);
buf.putLong(md.time);
packer.addPayload(buf.array());

bytes 数组长度需要为 5,第一个字节是 header,即 0xd2,其他 4 个字节需要是值

 ByteArrayOutputStream baos = new ByteArrayOutputStream();
            DataOutputStream dos = new DataOutputStream(baos);
            dos.writeLong(md.time);
            dos.close();
            byte[] longBytes = baos.toByteArray();

            ByteBuffer lBytes = ByteBuffer.allocate(4);
            for (int i = 0; i < 4; i++) {
                    lBytes.put(longBytes[i]);
            }

            ByteBuffer buf = ByteBuffer.allocate(5);
            buf.put((byte) 0xd2);
            buf.put(lBytes.array());

这不会产生错误,但接收时的时间值不正确。

有人可以告诉我如何将 INT32 而不是 UINT32 打包到我的 MessagePack 中,或者告诉我如何以正确的方式打包数据,以便在接收应用程序上正确解包数据吗?

<小时/>

接收应用程序写在 Go并使用 tinylib msgp解码数据的库

// ReadInt64Bytes tries to read an int64
// from 'b' and return the value and the remaining bytes.
// Possible errors:
// - ErrShortBytes (too few bytes)
// - TypeError (not a int)
func ReadInt64Bytes(b []byte) (i int64, o []byte, err error) {
    l := len(b)
    if l < 1 {
        return 0, nil, ErrShortBytes
    }

    lead := b[0]
    if isfixint(lead) {
        i = int64(rfixint(lead))
        o = b[1:]
        return
    }
    if isnfixint(lead) {
        i = int64(rnfixint(lead))
        o = b[1:]
        return
    }

    switch lead {
    case mint8:
        if l < 2 {
            err = ErrShortBytes
            return
        }
        i = int64(getMint8(b))
        o = b[2:]
        return

    case mint16:
        if l < 3 {
            err = ErrShortBytes
            return
        }
        i = int64(getMint16(b))
        o = b[3:]
        return

    case mint32:
        if l < 5 {
            err = ErrShortBytes
            return
        }
        i = int64(getMint32(b))
        o = b[5:]
        return

    case mint64:
        if l < 9 {
            err = ErrShortBytes
            return
        }
        i = getMint64(b)
        o = b[9:]
        return

    default:
        err = badPrefix(IntType, lead)
        return
    }
}

这会检查第一个字节,如果第一个字节等于 mint32,即 0xd2,则读取接下来的四个字节,这是使用 getmint32 得到的 long 值

func getMint32(b []byte) int32 {
    return (int32(b[1]) << 24) | (int32(b[2]) << 16) | (int32(b[3]) << 8) | (int32(b[4]))
}

最佳答案

在此特定问题中,接收应用程序必须接收 INT32,并且字节数组的长度需要为 5。第一个字节是标题 0xd2,如 OP 中所示。这告诉解码方法它是 INT32。接下来的 4 个 4 字节是时间值。

我忘记了 long 是 8 个字节,所以我们只需要使用纪元时间,它是一个整数。

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        DataOutputStream dos = new DataOutputStream(baos);
        dos.writeInt((int)(md.time/1000));
        dos.close();
        byte[] timeBytes = baos.toByteArray();


        ByteBuffer buf = ByteBuffer.allocate(5);
        buf.put((byte) 0xd2);//header
        buf.put(timeBytes);//time value (int32 bytes not uint32)

关于java - 如何使用 Java 将 INT32 打包到我的 MessagePack 中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47121532/

相关文章:

java - WireMock 性能和负载测试

java - (Project Tango)通过区域学习进行点云的旋转和平移

python - msgpack C# -> kafka -> Consumer (kafka-python) 失败,出现 ExtraData : unpack(b) received extra data

java - 从java中的Http请求中检索Msgpack

redis - 带有redis的消息包,其中数据量不大

java - Apache 紧缩错误

java - 根据用户输入计算星期几

java - 如何将特定类的日志信息记录到特定文件中?

python - Pandas msgpack vs 泡菜

C++ 消息包 : linker errors