如何使用 Kotlin 将 Int 转换为 ByteArray,然后将其转换回 Int?

问题描述 投票:0回答:6

这是我的代码:

Int -> ByteArray

private fun write4BytesToBuffer(buffer: ByteArray, offset: Int, data: Int) {
    buffer[offset + 0] = (data shr 24).toByte()
    buffer[offset + 1] = (data shr 16).toByte()
    buffer[offset + 2] = (data shr 8).toByte()
    buffer[offset + 3] = (data shr 0).toByte()
}

ByteArray -> Int

private fun read4BytesFromBuffer(buffer: ByteArray, offset: Int): Int {
    return (buffer[offset + 0].toInt() shl 24) or
           (buffer[offset + 1].toInt() shl 16) or
           (buffer[offset + 2].toInt() shl 8) or
           (buffer[offset + 3].toInt() and 0xff)
}

对于 -32,76832,767 之间的任何值都可以正常工作。 但是,它不适用于较大的值。例如:

val buffer = ByteArray(10)
write4BytesToBuffer(buffer, 0, 324)
read4BytesFromBuffer(buffer, 0) // It returns 324 ***OK***

val buffer = ByteArray(10)
write4BytesToBuffer(buffer, 0, 40171)
read4BytesFromBuffer(buffer, 0) // It returns -25365 ***ERROR***

你看到我哪里错了吗?

arrays kotlin integer byte
6个回答
15
投票

这是解决方案。

Int -> ByteArray

private fun write4BytesToBuffer(buffer: ByteArray, offset: Int, data: Int) {
    buffer[offset + 0] = (data shr 0).toByte()
    buffer[offset + 1] = (data shr 8).toByte()
    buffer[offset + 2] = (data shr 16).toByte()
    buffer[offset + 3] = (data shr 24).toByte()
}

或者以更短的方式

for (i in 0..3) buffer[offset + i] = (data shr (i*8)).toByte()

ByteArray -> Int

private fun read4BytesFromBuffer(buffer: ByteArray, offset: Int): Int {
    return (buffer[offset + 3].toInt() shl 24) or
           (buffer[offset + 2].toInt() and 0xff shl 16) or
           (buffer[offset + 1].toInt() and 0xff shl 8) or
           (buffer[offset + 0].toInt() and 0xff)
}

12
投票

我只使用 java.nio.ByteBuffer -

fun intToBytes(i: Int): ByteArray =
    ByteBuffer.allocate(Int.SIZE_BYTES).putInt(i).array()

fun bytesToInt(bytes: ByteArray): Int =
    ByteBuffer.wrap(bytes).int

8
投票

这是一个单行代码,将为您提供一个 ByteArray:

fun numberToByteArray (data: Number, size: Int = 4) : ByteArray = 
    ByteArray (size) {i -> (data.toLong() shr (i*8)).toByte()}

可选择设置字节数(大小),您可以转换 Shorts、Ints、Longs。

就这样称呼它:

var yourByteArray = numberToByteArray (yourNumberHere)

0
投票

您可以为此编写一个扩展函数

fun ByteArray.getIntAt(i: Int): Int {
    return (this[i].toInt() and 0xFF) or
            ((this[i + 1].toInt() and 0xFF) shl 8) or
            ((this[i + 2].toInt() and 0xFF) shl 16) or
            ((this[i + 3].toInt() and 0xFF) shl 24)
}

现在你可以使用它了:

val myInt = myByteArr.getIntAt(myIndex)

反之亦然:

private fun Int.toByteArray(): ByteArray {
    return byteArrayOf(
        (this and 0xFF).toByte(),
        ((this shr 8) and 0xFF).toByte(),
        ((this shr 16) and 0xFF).toByte(),
        ((this shr 24) and 0xFF).toByte()
    )
}

并使用它:

val myByteArray = myInt.toByteArray()

0
投票

如果您需要控制分配的字节大小,可以通过分析值范围来优化数组大小:

fun Int.toBytes(size: Int = Int.SIZE_BYTES): ByteArray = when {
    size == Byte.SIZE_BYTES -> byteArrayOf(this.toByte())
    size in Short.SIZE_BYTES until Int.SIZE_BYTES -> ByteBuffer.allocate(size).order(ByteOrder.BIG_ENDIAN).putShort(this.toShort()).array()
    size >= Int.SIZE_BYTES -> ByteBuffer.allocate(size).order(ByteOrder.BIG_ENDIAN).putInt(this).array()
    else -> throw IllegalArgumentException("Bytes size $size can not be empty or negative")
}

fun ByteArray.toInt(): Int = when {
    size == Byte.SIZE_BYTES -> first().toInt()
    size in Short.SIZE_BYTES until Int.SIZE_BYTES -> ByteBuffer.wrap(this).getShort().toInt()
    size >= Int.SIZE_BYTES -> ByteBuffer.wrap(this).getInt()
    else -> throw IllegalArgumentException("ByteArray is empty")
}

对我来说,在将数组写入/读取到具有大小的主要信息的文件中时很有帮助。

我的测试:

    @Test
    fun `int is converted to byte array and back`() {
        assertEquals(-127, -127.toBytes(1).toInt())
        assertEquals(0, 0.toBytes(1).toInt())
        assertEquals(1, 1.toBytes(1).toInt())
        assertEquals(2, 2.toBytes(1).toInt())
        assertEquals(3, 3.toBytes(1).toInt())
        assertEquals(4, 4.toBytes(1).toInt())
        assertEquals(5, 5.toBytes(1).toInt())
        assertEquals(127, 127.toBytes(1).toInt())
        assertEquals(128, 128.toBytes(2).toInt())
        assertEquals(1114, 1114.toBytes(3).toInt())
        assertEquals(98754332, 98754332.toBytes(4).toInt())
    }

顺便说一句,建议在这种情况下仅出于教育目的使用位移操作。因此,利用

ByteBuffer
可以为更大的转化提供更好的性能。

如果性能至关重要,请考虑探索本机库。


0
投票

我根据这个答案创建了2个扩展函数https://stackoverflow.com/a/71671967/4533459

private fun Int.toByteArray(): ByteArray =
    ByteBuffer.allocate(Int.SIZE_BYTES).putInt(this).array()

private fun ByteArray.toInt(): Int =
    ByteBuffer.wrap(this).int
© www.soinside.com 2019 - 2024. All rights reserved.