java 将 int 转换为短整型
我正在计算数据的 16 位校验和,我需要将其发送到服务器,服务器必须重新计算并与提供的校验和匹配。我得到的校验和值是 int 格式,但我只有 2 个字节用于发送该值。因此,我在调用 shortToBytes
int 转换为 short
> 方法。这工作正常,直到校验和值小于 32767,此后我得到负值。
问题是java没有无符号原语,所以我无法发送大于允许的有符号short
最大值的值。
我怎样才能做到这一点,将 int 转换为 Short 并通过网络发送,而不用担心截断和签名&无符号整数。
另外,我的两侧都运行着java程序。
private byte[] shortToBytes(short sh) {
byte[] baValue = new byte[2];
ByteBuffer buf = ByteBuffer.wrap(baValue);
return buf.putShort(sh).array();
}
private short bytesToShort(byte[] buf, int offset) {
byte[] baValue = new byte[2];
System.arraycopy(buf, offset, baValue, 0, 2);
return ByteBuffer.wrap(baValue).getShort();
}
I am calculating 16 bit checksum on my data which i need to send to server where it has to recalculate and match with the provided checksum. Checksum value that i am getting is in int but i have only 2 bytes for sending the value.So i am casting int
to short
while calling shortToBytes
method. This works fine till checksum value is less than 32767 thereafter i am getting negative values.
Thing is java does not have unsigned primitives, so i am not able to send values greater than max value of signed short
allowed.
How can i do this, converting int to short and send over the network without worrying about truncation and signed & unsigned int.
Also on both the side i have java program running.
private byte[] shortToBytes(short sh) {
byte[] baValue = new byte[2];
ByteBuffer buf = ByteBuffer.wrap(baValue);
return buf.putShort(sh).array();
}
private short bytesToShort(byte[] buf, int offset) {
byte[] baValue = new byte[2];
System.arraycopy(buf, offset, baValue, 0, 2);
return ByteBuffer.wrap(baValue).getShort();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您仍然获得与服务器相同的位值。因此,要查看正确的数值,请将
ByteBuffer.wrap(baValue).getShort()
替换为ByteBuffer.wrap(baValue).getInt()
。这应该为您提供与服务器相同的数值。You are still getting the same bit value as the server. So, to see the right numerical value replace the
ByteBuffer.wrap(baValue).getShort()
to aByteBuffer.wrap(baValue).getInt()
. This should give you the same numerical value as the server.char
是无符号 16 位类型。事实上,它是 Java 中唯一的无符号类型。您可以使用它来计算校验和,然后使用 ByteBuffer 来获取字节,或者简单地使用按位和右移来获取字节。请记住,
字节
是有符号的。char
is an unsigned 16 bit type. In fact it's the only unsigned type in Java. You can use it for calculating the checksum and then use aByteBuffer
to get the bytes or simply use bitwise and and right shifting to get the bytes.Bear in mind that
byte
s are signed.首先,Java
int
、short
和byte
类型都是有符号的,而不是无符号的。其次,当您将 Javaint
转换为short
等时,您将得到静默截断。这是否重要取决于校验和算法的性质。如果它是一个简单的求和,或者一个按位算法,那么当使用 Java 有符号整数实现时,该算法很可能就很好。例如,当由期望无符号值的东西解释时,那些“负”16 位校验和可能是正确的。
另一方面,乘法和除法的语义使得有符号和无符号风格必须单独处理。 (至少,这是我从查看 x86 指令集的不科学方法中推断出来的……它对于有符号与无符号乘法和除法有单独的指令。)
编辑 我知道您正在计算 CRC -16。由于可以通过移位和异或来计算,因此在计算过程中不应担心有符号数与无符号数。
简而言之,您无需担心任何事情。
Firstly, Java
int
,short
andbyte
types are all signed not unsigned. Secondly, when you cast a Javaint
to ashort
, etc you will get silent truncation.Whether this matters depends on the nature of the checksum algorithm. If it is a simple sum, or a bitwise algorithm there is a good chance that the algorithm is just fine when implemented using Java signed integers. For example, those "negative" 16bit checksums could be correct when interpreted by something expecting unsigned values.
On the other hand, the semantic of multiplication and division are such that signed and unsigned flavors have to be handled separately. (At least, that's what I infer from the unscientific approach of looking at the x86 instruction set ... which has separate instructions for signed versus unsigned multiplication and division.)
EDIT I understand that you are calculating CRC-16. Since that can be computed by shifting and XORing, there should be no concerns about signed versus unsigned numbers during the calculation.
In short, you don't have anything to worry about.
当你说你得到负值时,我假设你的意思是当你读取 16 位值并将其转换为整数时。其原因是,当
short
扩展为int
时,符号扩展会导致复制最高有效位(即 1)。简单的解决方法是使用0xFFFF
按位重建整数,这将确保只有最低有效的 16 位是非零的。When you say that you are getting negative values, I assume you mean when you read the 16 bit value and convert it to an integer. The reason for this is that sign extension causes the most significant bit (which is a 1) to be replicated when the
short
is widened to anint
. The simple workaround is to bitwise-and the reconstructed integer with0xFFFF
, which will ensure that only the least signficant 16 bits are non-zero.