1

我有一个字节数组(因为无符号字节不是一个选项)并且需要将其中的 4 个转换为 32 位 int。我正在使用这个:

byte rdbuf[] = new byte[fileLen+1];
int i = (rdbuf[i++]) | ((rdbuf[i++]<<8)&0xff00) | ((rdbuf[i++]<<16)&0xff0000) | ((rdbuf[i++]<<24)&0xff000000);

如果我不做所有的逻辑和,它会扩展字节,这显然不是我想要的。

在 c 中,这将是一个明智的选择。Java有更好的方法吗?

4

2 回答 2

11

您不必这样做,您可以使用ByteBuffer

int i = ByteBuffer.wrap(rdbuf).order(ByteOrder.LITTLE_ENDIAN).getInt();

如果您有许多整数要阅读,则代码变为:

ByteBuffer buf = ByteBuffer.wrap(rdbuf).order(ByteOrder.LITTLE_ENDIAN);

while (buf.remaining() >= 4) // at least four bytes
    i = bb.getInt();

Javadoc在这里。推荐用于必须处理二进制数据的任何情况(无论您是读取还是写入此类数据)。可以进行小端、大端甚至本地排序。(注意:默认为大端)。

(编辑:@PeterLawrey 正确地提到这看起来像小端数据,固定代码提取 - 另外,请参阅他的答案,了解如何将文件的内容直接包装到 a 中ByteBuffer

笔记:

  • ByteOrder有一个名为 的静态方法.nativeOrder(),它返回底层架构使用的字节顺序;
  • aByteBuffer有一个内置的偏移量;可以使用 查询当前偏移量.position(),并使用 修改当前偏移量.position(int).remaining()将返回从当前偏移量到结束要读取的剩余字节数;
  • 有相对方法将在缓冲区的当前偏移量处读取/写入,而绝对方法将在您指定的偏移量处读取/写入。
于 2013-01-14T13:09:25.730 回答
1

您可以使用直接的 ByteBuffer 来避免所有这些开销,而不是读入必须用 ByteBuffer 包装的 byte[] 来为您执行移位/掩码。

FileChannel fc = new FileInputStream(filename).getChannel();
ByteBuffer bb = ByteBuffer.allocateDirect(fc.size()).order(ByteBuffer.nativeOrder());
fc.read(bb);
bb.flip();
while(bb.remaining() > 0) {
    int n = bb.getInt(); // grab 32-bit from direct memory without shift/mask etc.
    short s = bb.getShort(); // grab 16-bit from direct memory without shift/mask etc.

    // get a String with an unsigned 16 bit length followed by ISO-8859-1 encoding.
    int len = bb.getShort() & 0xFFFF;
    StringBuilder sb = new StringBuilder(len);
    for(int i=0;i<len;i++) sb.append((char) (bb.get() & 0xFF));
    String text = sb.toString(); 
}
fc.close();
于 2013-01-14T13:19:55.797 回答