java和无符号值

nfs0ujit  于 2021-07-03  发布在  Java
关注(0)|答案(3)|浏览(305)

我正在分析datagramsocket中的无符号位。我总共有24位(或3个字节)输入-它们是:1个无符号8位整数后跟一个16位有符号整数。但是java从来不会将有符号字节以外的内容存储到字节/字节数组中?当java接受这些值时,会丢失最后的第8位吗?

DatagramSocket serverSocket = new DatagramSocket(666);
        byte[] receiveData = new byte[3]; <--Now at this moment I lost my 8th bit

        System.out.println("Binary Server Listing on Port: "+port);

        while (true)
        {
            DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
            serverSocket.receive(receivePacket);
            byte[] bArray = receivePacket.getData();
            byte b = bArray[0];

        }


自从我把它变成一个字节后,我现在丢失了第8位了吗?我初始化了一个3字节的字节数组,这不对吗?

qoefvg9y

qoefvg9y1#

不,你没有失去第8位。但不幸的是,java有两个“特性”,这使得处理这些值变得不合理:
它的所有基元类型都是有符号的;
将一个基元类型“展开”为另一个较大的基元类型时(例如,读取 byte 到一个 int 与这里的情况一样,“lower type”的符号位被展开。
这意味着,例如,如果你读byte 0x80 ,二进制翻译为:

1000 0000

当您将其读取为整数时,您将得到:

1111 1111 1111 1111 1111 1111 1000 0000
                              ^
                              This freaking bit gets expanded!

而你真正想要的是:

0000 0000 0000 0000 0000 0000 1000 0000

即,整数值128。因此,你必须掩盖它:

int b = array[0] & 0xff;

1111 1111 1111 1111 1111 1111 1000 0000 <-- byte read as an int, your original value of b
0000 0000 0000 0000 0000 0000 1111 1111 <-- mask (0xff)
--------------------------------------- <-- anded, give
0000 0000 0000 0000 0000 0000 1000 0000 <-- expected result

悲伤,但真实。
更一般地说:如果您希望操作大量面向字节的数据,我建议您看看bytebuffer,它会有很大帮助。但不幸的是,这并不能使您免于位掩码操作,它只是使您更容易一次读取给定数量的字节(作为基本类型)。

xpszyzbs

xpszyzbs2#

当java接受这些值时,会丢失最后的第8位吗?
不,当它被设置时,你只会得到一个负值。
所以要得到一个介于0和255之间的值,最简单的方法是使用以下内容:

int b = bArray[0] & 0xff;

首先 byte 被提升为 int ,它将对其进行符号扩展,如果原始值中的高位为1,则导致25个前导1位。这个 & 0xff 然后再去掉前24位:)

w51jfk4q

w51jfk4q3#

在java中,byte(以及short、int和long)只是一种有符号的数字数据类型。但是,这并不意味着在将它们视为无符号二进制数据时会丢失任何数据。如图所示, 10000000-128 作为有符号的十进制数。如果您处理的是二进制数据,只需将其视为二进制形式即可。

相关问题