Reputation: 9211
Is there a better/shorter way in creating byte array from constant hex than the version below?
byteArrayOf(0xA1.toByte(), 0x2E.toByte(), 0x38.toByte(), 0xD4.toByte(), 0x89.toByte(), 0xC3.toByte())
I tried to put 0xA1
without .toByte()
but I receive syntax error complaint saying integer literal does not conform to the expected type Byte
. Putting integer is fine but I prefer in hex form since my source is in hex string. Any hints would be greatly appreciated. Thanks!
Upvotes: 56
Views: 77559
Reputation: 1446
Just to improve upon the accepted solution, I took an inspiration from here. Basically, since Kotlin declares its own Byte
class, we can augment an operator onto its companion
object, like so:
operator fun Byte.Companion.get(vararg ints: Int) = ByteArray(ints.size) { pos -> ints[pos].toByte() }
Then, you can declare a Byte array more "naturally":
val bytes = Byte[0xA1, 0x2E, 0x38, 0xD4, 0x89, 0xC3]
Upvotes: 4
Reputation: 326
I just do:
val bytes = listOf(0xa1, 0x2e, 0x38, 0xd4, 0x89, 0xc3)
.map { it.toByte() }
.toByteArray()
Upvotes: 7
Reputation: 1689
If all your bytes were less than or equal to 0x7F
, you could put them directly:
byteArrayOf(0x2E, 0x38)
If you need to use bytes greater than 0x7F
, you can use unsigned literals to make a UByteArray
and then convert it back into a ByteArray
:
ubyteArrayOf(0xA1U, 0x2EU, 0x38U, 0xD4U, 0x89U, 0xC3U).toByteArray()
I think it's a lot better than appending .toByte()
at every element, and there's no need to define a custom function as well.
However, Kotlin's unsigned types are an experimental feature, so you may have some trouble with warnings.
Upvotes: 45
Reputation:
as an option you can create simple function
fun byteArrayOfInts(vararg ints: Int) = ByteArray(ints.size) { pos -> ints[pos].toByte() }
and use it
val arr = byteArrayOfInts(0xA1, 0x2E, 0x38, 0xD4, 0x89, 0xC3)
Upvotes: 54
Reputation: 89548
The issue is that bytes in Kotlin are signed, which means they can only represent values in the [-128, 127] range. You can test this by creating a ByteArray
like this:
val limits = byteArrayOf(-0x81, -0x80, -0x79, 0x00, 0x79, 0x80)
Only the first and last values will produce an error, because they are out of the valid range by 1.
This is the same behaviour as in Java, and the solution will probably be to use a larger number type if your values don't fit in a Byte
(or offset them by 128, etc).
Side note: if you print the contents of the array you've created with toInt
calls, you'll see that your values larger than 127 have flipped over to negative numbers:
val bytes = byteArrayOf(0xA1.toByte(), 0x2E.toByte(), 0x38.toByte(), 0xD4.toByte(), 0x89.toByte(), 0xC3.toByte())
println(bytes.joinToString()) // -95, 46, 56, -44, -119, -61
Upvotes: 12