8

我正在从 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 字节的字节数组是不是错了?

4

3 回答 3

12

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

不,当它被设置时,你最终会得到一个负值。

因此,要获得 0 到 255 之间的值,最简单的方法是使用如下内容:

int b = bArray[0] & 0xff;

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

于 2013-01-02T20:58:12.630 回答
9

不,您不会丢失第 8 位。但不幸的是,Java 有两个“特性”,这使得处理这些值变得非常困难:

  • 它的所有原始类型都已签名;
  • 当将一个原始类型“解包”为另一个更大尺寸的原始类型时(例如,将 a 读取byte到 anint就是这种情况),“较低类型”的符号位被扩展。

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

于 2013-01-02T21:03:19.190 回答
2

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

于 2013-01-02T20:59:13.923 回答