访问混合8/16/32位字的好方法

时间:2016-11-15 13:11:02

标签: arrays io stream kotlin

我在内存中有大量的二进制数据,我需要从随机访问的字节对齐地址进行读/写。但是,有时候我需要读/写8位字,有时候(大端)16位字,有时候(大端)32位字。

有一种天真的解决方案,即将数据表示为ByteArray并手动实现16/32位读/写:

class Blob (val image: ByteArray, var ptr: Int = 0) {
  fun readWord8(): Byte = image[ptr++]

  fun readWord16(): Short {
    val hi = readWord8().toInt() and 0xff
    val lo = readWord8().toInt() and 0xff
    return ((hi shl 8) or lo).toShort()
  }

  fun readWord32(): Int {
    val hi = readWord16().toLong() and 0xffff
    val lo = readWord16().toLong() and 0xffff
    return ((hi shl 16) or lo).toInt()
  }
}

(同样适用于writeWord8 / writeWord16 / writeWord32)。

有更好的方法吗?当Java本身已经在内部使用big-endian表示时,执行所有这些字节改组似乎效率很低......

重申一下,我需要读取和写入访问随机搜索,以及 8/16/32位访问到big-结束语。

1 个答案:

答案 0 :(得分:5)

您可以使用Java NIO ByteBuffer

val array = ByteArray(100)
val buffer = ByteBuffer.wrap(array)

val b = buffer.get()
val s = buffer.getShort()
val i = buffer.getInt()

buffer.put(0.toByte())
buffer.putShort(0.toShort())
buffer.putInt(0)

buffer.position(10)

新创建的ByteBuffer的字节顺序为BIG_ENDIAN,但仍可使用order(ByteOrder)函数进行更改。

另外,如果您想避免明确地创建ByteArray,请使用ByteBuffer.allocate(size)buffer.array()

有关ByteBuffer用法的更多信息:see this question