1. Introduction

Hexadecimal strings are often used in programming to represent binary data in a readable format. Consequently, tasks involving low-level data processing, cryptographic functions, or network protocols frequently require converting hex strings to byte arrays. Fortunately, Kotlin provides several efficient methods to handle this conversion.

In this tutorial, we’ll explore various ways to transform hex strings into byte arrays.

2. Using a for Loop

A straightforward way to convert a hex string to a byte array leverages the classic for loop. Consequently, we’ll iterate over the string and process each pair of hex digits manually:

fun hexStringToByteArrayCustom(hex: String): ByteArray {
    val length = hex.length
    val byteArray = ByteArray(length / 2)
    for (i in byteArray.indices) {
        val index = i * 2
        val byte = hex.substring(index, index + 2).toInt(16).toByte()
        byteArray[i] = byte
    }
    return byteArray
}

First, we initialize a ByteArray to half the length of the hex string, then loop through its indices. At each index, we extract two hex digits, convert them to a byte, and store them in the array.

Now, let’s test our method for correctness:

@Test
fun `convert hex string to byte array using for loop`() {
    val hexString = "48656C6C6F20576F726C64"
    val expectedByteArray = byteArrayOf(72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100)

    assertArrayEquals(expectedByteArray, hexStringToByteArrayUsingForLoop(hexString))
}

3. Using Standard Library Methods

We can also leverage Kotlin’s standard library to achieve our goal. Kotlin’s standard library provides basic methods to convert a hex string to a byte array:

fun hexStringToByteArrayUsingStandardLibraryMethods(hex: String): ByteArray {
    return hex.chunked(2)
      .map { it.toInt(16).toByte() }
      .toByteArray()
}

This method converts a hex string to a byte array by splitting the string into chunks of two characters and then mapping each chunk to a byte. Finally, it collects these bytes using toByteArray().

Similarly, we’ll test our method to assert that we obtain the correct byte array from a hex string:

@Test
fun `convert hex string to byte array using BigInteger using standard libraries methods`() {
    val hexString = "48656C6C6F20576F726C64"
    val expectedByteArray = byteArrayOf(72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100)

    assertArrayEquals(expectedByteArray, hexStringToByteArrayUsingStandardLibraryMethods(hexString))
}

4. Using hexToByteArray() Method

Another way to convert a hex string to a byte array is by using Kotlin’s built-in hexToByteArray() method:

@OptIn(ExperimentalStdlibApi::class)
@Test
fun `convert hex string to byte array using hexToByteArray`() {
    val hexString = "48656C6C6F20576F726C64"
    val expectedByteArray = byteArrayOf(72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100)

    assertArrayEquals(expectedByteArray, hexString.hexToByteArray())
}

This test uses the hexToByteArray() method to convert a hex string to a byte array. However, this method is an experimental API, so we’ll need to annotate our method with the @OptIn annotation for ExperimentalStdlibApi to be allowed to use it.

5. Using BigInteger

The BigInteger class provides a convenient method for parsing a hex string and obtaining the corresponding byte array. This approach is particularly convenient for converting large hex strings:

fun hexStringToByteArrayUsingBigInteger(hexString: String): ByteArray {
    val bigInteger = BigInteger(hexString, 16)
    return bigInteger.toByteArray()
}

We convert a hex string to a byte array by creating a BigInteger with base 16 from the hex string and then calling toByteArray() on the BigInteger to return the corresponding byte array.

Again, we should ensure this works as expected:

@Test
fun `convert hex string to byte array using BigInteger`() {
    val hexString = "48656C6C6F20576F726C64"
    val expectedByteArray = byteArrayOf(72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100)
        
    assertArrayEquals(expectedByteArray, hexStringToByteArrayUsingBigInteger(hexString))
}

This test shows that we correctly obtain a byte array from a hex string using our helper method.

6. Conclusion

In this article, we’ve explored various ways of converting a hex string to a byte array in Kotlin. We started with a simple loop to convert hex strings. We also used functions built into Kotlin’s standard library to achieve our solution. Finally, we utilized the BigInteger class to convert hex numbers to byte arrays.

As always, the code from this article is available over on GitHub.