如何在Java中将带符号的16位整数转换为无符号16位整数?

时间:2015-02-24 22:09:28

标签: java c++ bytearray unsigned bytebuffer

我有我的下面布局,我需要在其中表示我的数据,然后最后我需要制作一个字节数组。我需要用Java代码以下面的格式表示我的数据,然后将字节数组发送到我的C ++程序,然后c ++程序解压缩字节数组并从中提取相关内容 -

// below is my data layout -
//
// key type - 1 byte
// key len - 1 byte
// key (variable size = key_len)
// timestamp (sizeof uint64_t)
// data size (sizeof uint16_t), this is unsigned 16-bit integer.
// data (variable size = data size)

所以我在Java中开始这样就可以在一个简单的用例中正常工作,这个用例会产生一个单字节数组,但我认为我的dataSize计算错误,因为我使用的是Short dataSize可以取最大值32767dataSize规范为uint16_t,如上所示无符号16位整数,可以采用最大值超过32767

byte keyType = 101;
byte keyLength = 3;
byte[] key = {27, 55, 111};
long timestamp = System.currentTimeMillis();

byte[] data = "string data".getBytes("UTF-8");

// this is looking wrong to me since dataSize is uint16_t in my C++ specifications as shown above
short dataSize = (short) data.length;

int totalSize = (1 + 1 + keyLength + 8 + 2 + dataSize);
ByteBuffer bytes = ByteBuffer.allocate(totalSize);

bytes.put(keyType);
bytes.put(keyLength);
bytes.put(key);
bytes.putLong(timestamp);

// so this is also wrong
// what is the right way to send the dataSize?
bytes.putShort(dataSize);
bytes.put(data);

// write everthing as a single byte array:
byte[] byteArray = bytes.array();

假设数据长度为37714(data.length),那么dataSize将为负数-27822

所以我的问题是 - 有没有什么方法可以在java中使用无符号的16位整数,我可以在上面的代码中使用或以某种方式来编译它?

我的上述代码是否与上述规格相符,或者如果我们有一些大字符串出现,可能会出现问题。

1 个答案:

答案 0 :(得分:3)

Java唯一的无符号类型是char,它恰好是16位宽。但是,这不是表示长度的正确选择:您应该在内部使用int,并且仅在序列化和反序列化期间转换为16位短路。

int dataSize = data.length;
...
bytes.putShort((short)(dataSize & 0xFFFF));

short tmp = getShort(...);
int dataSize = ((int)tmp) & 0xFFFF;

0xFFFF是一个16位“掩码”,可以切断int的不需要的位。请注意,如果在反序列化期间tmp恰好为负数,则屏蔽将使其再次为正,从而生成已发送给您的值。