我有一个大小为 64 的字节数组。我从 UsbConnection.bulkTRansfer()
接收 64 字节的数据。我想检查我是否收到“Sync”数据包。 “Sync”是一个长常量,值为 4006390527l
。这是我的代码。
byte[] buffer = new byte[64];
bytesReceived += usbConnection.bulkTransfer(usbEndpointIn, buffer, 64, 2000);
String l=Base64.encodeToString(buffer,0);
long ll=Long.parseLong(l);
if(C.SYNC_PAD_TO_HOST == ll) {
Log.d(TAG,"SyncReceived");//This is the Sync
gotSync=true;
System.arraycopy(buffer, 0, rcvbuf, 0, buffer.length);
}
我得到了非常奇怪的结果。 if 条件永远不会变为真。这里出了什么问题。
最佳答案
这里有一些问题。全速 USB 同步是 32 位。 int
能够包含数据,但不能作为无符号整数。您的代码将其存储为 long
的唯一原因是将 0x80000000
到 0xFFFFFFFF
的值存储为正数。但是,仅使用 long
的最低有效 32 位。
要计算流中的第一个小端无符号 32 位数字并将其存储为 long
,请使用:
long ll = (buffer[0] & 0xFF)
| ((buffer[1] & 0xFF) << 8)
| ((buffer[2] & 0xFF) << 16)
| ((buffer[3] & 0xFFL) << 24);
以下是所发生情况的详细说明:
您的十六进制同步数据包是0x17E1444C
。 USB 使用小尾数法传输该值,这意味着首先发送最低有效字节。通过网络,字节按以下顺序出现:
4C 44 E1 17
分解步骤:
long ll = buffer[0] & 0xFF;
// ll == 0x4C & 0x000000FF
// == (long) 0x0000004C
// == 0x000000000000004C
ll |= (buffer[1] && 0xFF) << 8;
// ll == 0x000000000000004C | ((0x44 & 0x000000FF) << 8)
// == 0x000000000000004C | (0x00000044 << 8)
// == 0x000000000000004C | 0x00004400
// == 0x000000000000004C | (long) 0x00004400
// == 0x000000000000004C | 0x0000000000004400
// == 0x000000000000004C
ll |= (buffer[2] & 0xFF) << 16;
// ll == 0x000000000000444C | ((0xE1 & 0x000000FF) << 16)
// == 0x000000000000444C | (0x000000E1 << 16)
// == 0x000000000000444C | 0x00E10000
// == 0x000000000000444C | (long) 0x00E10000
// == 0x000000000000444C | 0x0000000000E10000
// == 0x0000000000E1444C
最后一个包含说明了我们使用 & 0xFF
的原因。如果不使用按位 AND,以下是不使用 & 0xFF
时发生的情况:
ll |= buffer[2] << 16;
// ll == 0x000000000000444C | ((int) 0xE1) << 16)
// == 0x000000000000444C | (0xFFFFFFE1 << 16)
// == 0x000000000000444C | 0xFFE10000
// == 0x000000000000444C | (long) 0xFFE10000
// == 0x000000000000444C | 0xFFFFFFFFFFE10000
// == 0xFFFFFFFFFFE1444C
这是因为 E1
超过了最大正字节
(0x7F
),因此它被视为负数。当直接转换为 int
时,负号被保留。为了避免这种行为,我们使用完整的 8 位 AND 将其转换为 int
。
现在回到流程。最后一个字节:
ll |= (buffer[3] & 0xFFL) << 24;
// ll == 0x0000000000E1444C | ((0x17 & 0x00000000000000FF) << 24)
// == 0x0000000000E1444C | (0x0000000000000017 << 24)
// == 0x0000000000E1444C | 0x0000000017000000
// == 0x0000000017E1444C
您会注意到上面执行的最后一个按位 AND 使用的是 0xFF
的 long
版本。这是因为,如果最低有效字节超过最大正字节 (0x7F
),则左移 24 位(或更高位)有可能产生负 int
。想象一下最后一个字节不是 17
,而是 A7
。以下是使用 & 0xFF
而不是 & 0xFFL
时会发生的情况:
ll |= (buffer[3] & 0xFF) << 24;
// ll == 0x0000000000E1444C | ((0xA7 & 0x000000FF) << 24)
// == 0x0000000000E1444C | (0x000000A7 << 24)
// == 0x0000000000E1444C | 0xA7000000
// == 0x0000000000E1444C | (long) 0xA7000000
// == 0x0000000000E1444C | 0xFFFFFFA7000000
// == 0xFFFFFFFFA7E1444C
关于java - 如何在java中比较64字节数组的内容与long?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21025743/