如何在Java中将有符号16位整数转换为无符号16位整数?
我有下面的布局,我需要在其中表示我的数据,然后最后我需要用它制作一个字节数组。我需要用java代码把我的数据用下面的格式表示,然后把字节数组发送到C++程序,然后C++程序解压缩字节数组并从中提取相关的东西-< /p>如何在Java中将有符号16位整数转换为无符号16位整数?,java,c++,bytearray,unsigned,bytebuffer,Java,C++,Bytearray,Unsigned,Bytebuffer,我有下面的布局,我需要在其中表示我的数据,然后最后我需要用它制作一个字节数组。我需要用java代码把我的数据用下面的格式表示,然后把字节数组发送到C++程序,然后C++程序解压缩字节数组并从中提取相关的东西-< /p> // below is my data layout - // // key type - 1 byte // key len - 1 byte // key (variable size = key_len) // timestamp (sizeof uint64_t) //
// 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
计算是错误的,因为我对dataSize
使用Short
,它的最大值为32767
,但是dataSize
规范是错误的uint16\u 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位整数,我可以在上面的代码中使用它,或者用某种方法来转换它
我上面的代码是否符合上述规范,或者如果出现一些大字符串,是否存在任何可能导致问题的错误。Java唯一的无符号类型是
char
,它恰好是16位宽。但是,这并不是表示长度的正确选择:您应该在内部使用int
,并且仅在序列化和反序列化期间转换为16位short
int dataSize = data.length;
...
bytes.putShort((short)(dataSize & 0xFFFF));
及
0xFFFF
是一个16位的“掩码”,用于切断int
中不需要的位。请注意,如果反序列化过程中tmp
恰好为负值,屏蔽将使其再次为正值,从而生成发送给您的值。Java中唯一的无符号16位整数是char
,但您可以通过简单的强制转换将short
转换为char
。但是您最好使用int
。为什么dataSize首先需要是有符号的short?只需声明它为int,并检查它是否小于65536,然后再调用putShort()。@LeeDanielCrocker您能提供一个示例吗?或者你的意思是说dasblinkenlight在下面建议了什么?他的版本有点风险,因为如果data.length>65536(并且你没有告诉我们这是从哪里来的,所以我们不知道),他的代码会默默地忽略这个错误,可能会截断数据。我建议明确检查该案例,并在需要时处理错误。谢谢您的建议。在我们的例子中,C++程序正在读取<代码> DATABASE 作为<代码> UTI1616T 。基本上我们需要从java程序中写入数据,并从C++中读取它。因此C++程序正在阅读<代码>数据化< /代码>作为<代码> UTI1616T 。如果我这样做int size=37714;System.out.println((短)(大小和0xFFFF))
它打印出负数,这就是它存储在字节中的内容。putShort
对吗?但是C++会正确地解码吗?到目前为止,我们所使用的C++应用程序不能正确地解码它。它在C++程序中是这样读的:<代码> Val= NtoHS(*RealTytReCube(缓冲));代码> @戴维C++应重新解释负数为由相同的16位组成的大正数。您的代码是否正确解释了一些数字ntohs
可能会对字节进行重新排序,因此Java可能也需要进行一些重新排序。
short tmp = getShort(...);
int dataSize = ((int)tmp) & 0xFFFF;