java - 将 4 个字节转换为一个无符号的 32 位整数并存储在一个 long 中

标签 java bit-manipulation

我正在尝试读取 Java 中的二进制文件。我需要读取无符号 8 位值、无符号 16 位值和无符号 32 位值的方法。什么是最好的(最快,最好看的代码)来做到这一点?我在 C++ 中完成了这个并做了这样的事情:

uint8_t *buffer;
uint32_t value = buffer[0] | buffer[1] << 8 | buffer[2] << 16 | buffer[3] << 24;

但是在 Java 中,如果例如 buffer[1] 包含一个设置了符号位的值,因为左移的结果是一个 int (?)。而不是在特定位置仅在 0xA5 中进行 OR:ing,而是在 0xFFFFA500 中进行 OR:s 或类似的东西,这会“损坏”两个顶部字节。

我现在有一个代码,看起来像这样:

public long getUInt32() throws EOFException, IOException {
    byte[] bytes = getBytes(4);
    long value = bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24);
    return value & 0x00000000FFFFFFFFL;
}

如果我想转换四个字节 0x67 0xA5 0x72 0x50,结果是 0xFFFFA567 而不是 0x5072A567。

编辑:效果很好:

public long getUInt32() throws EOFException, IOException {
    byte[] bytes = getBytes(4);
    long value = bytes[0] & 0xFF;
    value |= (bytes[1] << 8) & 0xFFFF;
    value |= (bytes[2] << 16) & 0xFFFFFF;
    value |= (bytes[3] << 24) & 0xFFFFFFFF;
    return value;
}

但是没有更好的方法来做到这一点吗?对于这样一个简单的事情,10 位操作似乎有点“有点”..(看到我在那里做了什么?)=)

最佳答案

更常规的版本首先将字节转换为其无符号值作为整数:

public long getUInt32() throws EOFException, IOException {
    byte[] bytes = getBytes(4);
    long value = 
        ((bytes[0] & 0xFF) <<  0) |
        ((bytes[1] & 0xFF) <<  8) |
        ((bytes[2] & 0xFF) << 16) |
        ((long) (bytes[3] & 0xFF) << 24);
    return value;
}

不要纠结于位操作的数量,编译器很可能会将这些优化为字节操作。

此外,您不应该为了避免符号而将 long 用于 32 位值,您可以使用 int 并忽略它被签名最多的事实的时间。参见 this answer .

更新:需要将最高有效字节强制转换为 long,因为否则其最高有效位将被移入 32 位整数的符号位,可能使其为负数。

关于java - 将 4 个字节转换为一个无符号的 32 位整数并存储在一个 long 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13203426/

相关文章:

java - 当循环 Akka 调度程序的 Runnable 花费的时间比循环时间长时会发生什么?

java - AES 解密适用于 Solaris 机器 SunJCE,但不适用于具有 IBMJCE 的 AIX 机器

java - 为什么当你有 finalize() 时关闭资源很重要

javascript - 如何在 JavaScript 中添加位

java - 如何设置推断类型列表 getter 和 setter?

c - 是否可以通过少于 9 次比较来检查 2 组 3 个整数中的任何一个是否相等?

java - 将按位运算Java代码转换为PHP

c - 使用长的位列表

c++ - 关于枚举和按位运算

java - interestOps 抛出 IllegalArgumentException