Java和无符号值

时间:2013-01-02 20:55:36

标签: java bit-manipulation

我正在解析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];

        }

enter image description here

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

3 个答案:

答案 0 :(得分:12)

  

当java接收这些值时,你会丢失最后的第8位吗?

没有。在设置时,你最终会得到一个负值。

所以要获得0到255之间的值,最简单的方法是使用这样的东西:

int b = bArray[0] & 0xff;

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

答案 1 :(得分:7)

不,你不会失去第8位。但不幸的是,Java有两个“功能”,这使得处理这些值更难以合理:

  • 所有原始类型都已签名;
  • 当将原始类型“展开”为具有更大尺寸的另一个基本类型时(例如,将byte读取到int,就像这里的情况一样),“下”的符号位类型“已扩展。

这意味着,例如,如果您读取字节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,它可以提供很多帮助。但不幸的是,这不会让你无法进行位掩码操作,只是它可以更容易地读取给定数量的字节作为时间(作为基本类型)。

答案 2 :(得分:2)

在Java中,byte(以及short,int和long)只是签名的数字数据类型。但是,当将它们视为 unsigned 二进制数据时,这并不意味着任何数据丢失。如图所示,10000000-128为带符号的十进制数。如果您正在处理二进制数据,只需将其视为二进制形式,您就可以了。