访问混合 8/16/32 位字的好方法
Posted
技术标签:
【中文标题】访问混合 8/16/32 位字的好方法【英文标题】:Good way to access mixed 8/16/32-bit words 【发布时间】:2016-11-15 13:11:02 【问题描述】:我在内存中有一大块二进制数据,我需要从随机访问的字节对齐地址读取/写入。但是,有时我需要读/写 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 本身已经在内部使用大端表示时,执行所有这些字节洗牌似乎效率很低......
重申一下,我需要 读写访问权限、随机搜索和 8/16/32 位访问权限字节序。
【问题讨论】:
【参考方案1】:你可以使用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。
【讨论】:
.postion()
不会创建新缓冲区,只是返回用不同指针包装的相同数据,对吧?我不想继续复制我的 blob。
@Cactus,是的,buffer.array() === newBuffer.array()
是 true
。
@Cactus,我查看了position
的文档,发现它实际上修改了this
缓冲区并返回它,因此甚至不需要使用返回值。修复了答案,对不起。以上是关于访问混合 8/16/32 位字的好方法的主要内容,如果未能解决你的问题,请参考以下文章