java - 如何在java中比较64字节数组的内容与long?

标签 java

我有一个大小为 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 的唯一原因是将 0x800000000xFFFFFFFF 的值存储为正数。但是,仅使用 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 使用的是 0xFFlong 版本。这是因为,如果最低有效字节超过最大正字节 (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/

相关文章:

java - 个性化的 ApplicationContextInitializer 可能会导致错误无法打开 ServletContext 资源 [/WEB-INF/applicationContext.xml]?

java - Spring进程自动运行

java - 比较两个分数的问题

java - Android 如何响应主页点击

java - 带有 TextFormatter 和/或 UnaryOperator 的 JavaFX 8 中用于整数的数字文本字段

java - 编译程序时出现堆栈溢出错误

java - 检查一个数是否是两个素数的和

重载方法时Java方法继承问题

java - 二维数组,查找数组中重复次数最多的数字

java - Android Location API 不显示模拟位置 onLocationChanged