访问混合 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 位字的好方法的主要内容,如果未能解决你的问题,请参考以下文章

混色的好插值方法?

让 ViewControllers 访问 NavigationController 的好方法?

我可以假设计算能力 3.0 中没有银行冲突吗?

08_stm32位带操作

用 PHP/MySQL 封装数据访问的好方法是啥?

C# 是不是有一种存储多个对象并且仍然易于访问的好方法 [关闭]