【问题标题】:How to get an unsigned integer from a byte array in Kotlin JVM?如何从 Kotlin JVM 中的字节数组中获取无符号整数?
【发布时间】:2018-12-26 07:46:00
【问题描述】:

Kotlin 1.3 引入了 unsigned integer types,但我似乎无法弄清楚如何在 Kotlin JVM 中从 ByteArray 获取无符号整数。

Kotlin Native 有一个方便的 ByteArray.getUIntAt() 方法,但 Kotlin JVM 不存在这种方法。

val bytes: ByteArray = byteArrayOf(1, 1, 1, 1)
val uint: UInt // = ???

我在这里有什么选择?有没有比使用ByteBuffer 更优雅的方法,或者通过位移来摆脱这种方式?

【问题讨论】:

  • 你可以使用val uint = bytes[index].toUInt()
  • @Moinkhan 不,这只是转换index 处的单个字节。我需要将 4 个字节转换为单个无符号整数。
  • 但是逻辑是什么......所有元素都应该添加还是什么??
  • getUIntAt() 也接受相同的索引
  • @Moinkhan 没有逻辑。 UInt 是一个 32 位有符号整数。 32 位是 4 个字节。

标签: arrays kotlin jvm byte unsigned-integer


【解决方案1】:

正如 cmets 中提到的,在 Kotlin 的 JVM 版本中没有开箱即用的解决方案。与 Kotlin/Native 函数执行相同操作的扩展函数可能如下所示:

fun ByteArray.getUIntAt(idx: Int) =
    ((this[idx].toUInt() and 0xFFu) shl 24) or
            ((this[idx + 1].toUInt() and 0xFFu) shl 16) or
            ((this[idx + 2].toUInt() and 0xFFu) shl 8) or
            (this[idx + 3].toUInt() and 0xFFu)

fun main(args: Array<String>) {

    // 16843009
    println(byteArrayOf(1, 1, 1, 1).getUIntAt(0))

    // 4294967295, which is UInt.MAX_VALUE
    println(byteArrayOf(-1, -1, -1, -1).getUIntAt(0))
}

【讨论】:

    【解决方案2】:

    为了扩展@Alexander 的excellent answer,我编写了一个接受少于四个值的字节数组的版本。我发现这在使用有符号和无符号整数的混合解析 ByteArrays 时特别有用(在我的情况下是蓝牙特征更新通知) 我需要分割成子数组。

    fun ByteArray.fromUnsignedBytesToInt(): Int {
    //Note: UInt is always 32 bits (4 bytes) regardless of platform architecture
    //See https://kotlinlang.org/docs/basic-types.html#unsigned-integers
        val bytes = 4
        val paddedArray = ByteArray(bytes)
        for (i in 0 until bytes-this.size) paddedArray[i] = 0
        for (i in bytes-this.size until paddedArray.size) paddedArray[i] = this[i-(bytes-this.size)]
    
        return (((paddedArray[0].toULong() and 0xFFu) shl 24) or
                ((paddedArray[1].toULong() and 0xFFu) shl 16) or
                ((paddedArray[2].toULong() and 0xFFu) shl 8) or
                (paddedArray[3].toULong() and 0xFFu)).toInt()
    }
    

    下面的测试类确认了预期值:

    import org.junit.Test
    import org.junit.Assert.*
    
    internal class ByteArrayExtKtTest {
        @Test
        fun testAsUnsignedToIntTwoBytes() {
            val bytes = byteArrayOf (0x0A.toByte(), 0xBA.toByte())
            assertEquals(2746, bytes.fromUnsignedBytesToInt())
        }
    
        @Test
        fun testAsUnsignedToIntFourBytes() {
            val bytes = byteArrayOf(1,1,1,1)
            assertEquals(16843009, bytes.fromUnsignedBytesToInt())
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-10-10
      • 1970-01-01
      • 2011-12-07
      • 2012-04-01
      • 2021-05-02
      • 1970-01-01
      • 2010-12-01
      相关资源
      最近更新 更多