0

I need to convert a value of type Long to Base64 encoding.

I tried converting to a byte[] and then passing that to Base64.encodeToString but I get the wrong answer.

I looked through many of the examples here but none helped. Maybe I am misunderstanding how encodeToString works?

theblitz
  • 6,683
  • 16
  • 60
  • 114
  • For me it doesn't make sense. Base64 is an encoding that by definition applies to a series of _bytes_. Not to any other data types like integers or floating point numbers. Can you precise what you want any why? – prapin Oct 17 '20 at 21:29
  • Do you have the answer you're meant to get? Posting that and the ``Long`` would probably help people work it out. Or is it a "put the answer in and see if you win" kind of thing? Off the top of my head, it could be affected by things like the Base64 encoding (is it padded? is it using URL-safe characters? Check the encoding flags) and maybe endianness? Is this Kotlin-specific or is it one of those coding challenge sites where you can use any language? – cactustictacs Oct 17 '20 at 21:41

1 Answers1

1

Using this answer to the question "How do I convert Long to byte[] and back in Java":

import java.nio.ByteBuffer
import java.util.Base64

fun main() {
    val number: Long = 12345678
    val encodedNumberString = Base64.getEncoder().encodeToString(longToBytes(number))
    println("Number: $number.")
    println("Encoded number: \"$encodedNumberString\".")
    val decodedNumberBytes = Base64.getDecoder().decode(encodedNumberString)
    val decodedNumber = bytesToLong(decodedNumberBytes)
    println("Decoded number: $decodedNumber.")
}

private fun longToBytes(number: Long): ByteArray {
    val buffer = ByteBuffer.allocate(java.lang.Long.BYTES)
    buffer.putLong(number)
    return buffer.array()
}

private fun bytesToLong(bytes: ByteArray): Long {
    val buffer = ByteBuffer.allocate(java.lang.Long.BYTES)
    buffer.put(bytes)
    // Prepare the byte buffer to enable reading from it.
    buffer.flip()
    return buffer.long
}

This is the output on my system:

Number: 12345678.
Encoded number: "AAAAAAC8YU4=".
Decoded number: 12345678.

Update: Base64

Base64 is a way to convert binary data to text and uses a safe subset of 64 characters that can be transferred in for example an e-mail attachment. Not all 256 values in a byte can be sent without problems, so only 6 bits (2^6 = 64) are encoded in each character. This means that 3 bytes can be transferred in 4 characters (the overhead is 33%).

Update: extension functions

As Alex.T already mentioned in the comment, Kotlin enables you to make the Long <-> ByteArray conversions a lot shorter using extension functions (assuming the ByteArray implementation has an accessible backing array):

fun Long.toByteArray(): ByteArray = ByteBuffer.allocate(java.lang.Long.BYTES).apply { putLong(this@toByteArray) }.array()
fun ByteArray.toLong(): Long = ByteBuffer.allocate(java.lang.Long.BYTES).apply { put(this@toLong); flip() }.long

fun main() {
    val number = 12345678L
    val encodedNumberString = Base64.getEncoder().encodeToString(number.toByteArray())
    println("Encoded number: \"$encodedNumberString\".")
    val decodedNumber = Base64.getDecoder().decode(encodedNumberString).toLong()
    println("Decoded number: $decodedNumber.")
}
Freek de Bruijn
  • 3,552
  • 2
  • 22
  • 28
  • 1
    Just as a note, you could write those functions as `fun Long.toByteArray(): ByteArray =ByteBuffer.allocate(java.lang.Long.BYTES).apply { putLong(this@toByteArray)}.array()` AND `fun ByteArray.toLong() = ByteBuffer.allocate(java.lang.Long.BYTES).apply { put(this@toLong); flip() }.long` in Kotlin – AlexT Oct 17 '20 at 22:15
  • Maybe I am misunderstanding something. I got the same result but that doesn't look like a Base 64 number unless I don't understand what Base64 means. I just assumed to was the same as Hex but with 64 as the base instead of 16. – theblitz Oct 17 '20 at 22:15