【发布时间】:2023-03-13 20:01:01
【问题描述】:
我正在尝试用 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 (?),该值设置了符号位。而不是 OR:ing 仅在特定位置的 0xA5 中它 OR:s 在 0xFFFFA500 或类似的东西中,这会“损坏”两个顶部字节。
我现在有一个代码,如下所示:
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 位操作似乎“有点”多。(看看我在那里做了什么?)=)
【问题讨论】:
-
如果您使用的变量很长,那么 ALU 将始终在 64 位上执行操作。如果变量是 int,则 ALU 总是在 32 位上进行操作(而 ALU 功能的其他 32 位未使用)。对字节的操作很可能使 ALU 的 58 位未使用。这些操作总是在一个时钟周期内发生,所以说 10 位太多了。
-
不,您的工作实施正是正确的方法。
-
您不需要上面代码中的最后一个位和操作: value |= (bytes[3]
标签: java bit-manipulation