如何在Java中将有符号的16位整数转换为无符号的16位整数?
How to convert signed 16 bit integer to unsigned 16 bit integer in Java?
我有下面的布局,我需要在其中表示我的数据,最后我需要从中创建一个字节数组。我需要从 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
for the dataSize
which can take maximum value as 32767
but dataSize
specification is uint16_t
as shown above which is unsigned 16-bit整数 取最大值大于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 位整数,我可以在上面的代码中使用它或以某种方式转换它?
我上面的代码是否符合上面的规范,或者如果我们有一些大字符串出现,是否有任何错误可能会导致问题。
Java唯一的无符号类型是char
,而且正好是16位宽。但是,这不是表示长度的正确选择:您应该在内部使用 int
,并且仅在序列化和反序列化期间将 to/from 转换为 16 位短。
int dataSize = data.length;
...
bytes.putShort((short)(dataSize & 0xFFFF));
和
short tmp = getShort(...);
int dataSize = ((int)tmp) & 0xFFFF;
0xFFFF
是一个 16 位 "mask",它切断了 int
不需要的位。请注意,如果 tmp
在反序列化期间恰好为负数,则屏蔽会使其再次变为正数,从而生成已发送给您的值。
我有下面的布局,我需要在其中表示我的数据,最后我需要从中创建一个字节数组。我需要从 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
for the dataSize
which can take maximum value as 32767
but dataSize
specification is uint16_t
as shown above which is unsigned 16-bit整数 取最大值大于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 位整数,我可以在上面的代码中使用它或以某种方式转换它?
我上面的代码是否符合上面的规范,或者如果我们有一些大字符串出现,是否有任何错误可能会导致问题。
Java唯一的无符号类型是char
,而且正好是16位宽。但是,这不是表示长度的正确选择:您应该在内部使用 int
,并且仅在序列化和反序列化期间将 to/from 转换为 16 位短。
int dataSize = data.length;
...
bytes.putShort((short)(dataSize & 0xFFFF));
和
short tmp = getShort(...);
int dataSize = ((int)tmp) & 0xFFFF;
0xFFFF
是一个 16 位 "mask",它切断了 int
不需要的位。请注意,如果 tmp
在反序列化期间恰好为负数,则屏蔽会使其再次变为正数,从而生成已发送给您的值。