1

I have a big lump of binary data in memory and I need to read/write from randomly accessed, byte-aligned addresses. However, sometimes I need to read/write 8-bit words, sometimes (big-endian) 16-bit words, and sometimes (big-endian) 32-bit ones.

There's the naïve solution of representing the data as a ByteArray and implementing 16/32-bit reads/writes by hand:

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()
  }
}

(and similarly for writeWord8/writeWord16/writeWord32).

Is there a better way to do this? It just seems so inefficient doing all this byte-shuffling when Java itself already uses big-endian representation inside...

To reiterate, I need both read and write access, random seeks, and 8/16/32-bit access to big-endian words.

Cactus
  • 27,075
  • 9
  • 69
  • 149

1 Answers1

5

You can use 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)

The byte order of a newly created ByteBuffer is BIG_ENDIAN, but it can still be changed with the order(ByteOrder) function.

Also, use ByteBuffer.allocate(size) and buffer.array() if you want to avoid creating a ByteArray explicily.

More about ByteBuffer usage: see this question.

Community
  • 1
  • 1
hotkey
  • 140,743
  • 39
  • 371
  • 326
  • `.postion()` doesn't make a new buffer, just returns the same data wrapped with a different pointer, right? I wouldn't want to keep copying my blob around. – Cactus Nov 15 '16 at 13:50
  • 1
    @Cactus, yep, `buffer.array() === newBuffer.array()` is `true`. – hotkey Nov 15 '16 at 13:54
  • 1
    @Cactus, I've checked the docs for `position` and found that it actually modifies `this` buffer and returns it, so that there's even no need to use the return value. Fixed the answer, sorry. – hotkey Nov 15 '16 at 15:55