Convert Hex value to Base64 using Kotlin - kotlin

I have this value:
263e5df7a93ec5f5ea6ac215ed957c30
When I fill this in on: https://8gwifi.org/base64Hex.jsp (Hex to Base64)
It gives me back:
Jj5d96k+xfXqasIV7ZV8MA==
This is the expected value. However, when I try this in Kotlin,
val encodedHexB64 = Base64.encodeToString("263e5df7a93ec5f5ea6ac215ed957c30".toByteArray(UTF_8), Base64.NO_WRAP)
It gives me back:
MjYzZTVkZjdhOTNlYzVmNWVhNmFjMjE1ZWQ5NTdjMzA=
How to get the correct value in Kotlin?

To complete the previous:
val input = "263e5df7a93ec5f5ea6ac215ed957c30"
val bytes = input.chunked(2).map { it.toInt(16).toByte() }.toByteArray()
val encodeBase64 = Base64.encodeToString(bytes, Base64.DEFAULT)
Now you have: Jj5d96k+xfXqasIV7ZV8MA==

It looks like the input string represents 16 bytes, where each byte is coded with two hex digit chars of that string.
On the contrary toByteArray(UTF_8) encodes the string in UTF-8 encoding turning each char into one or more bytes. When you convert these bytes to base64, first you get the longer result and second — these are completely different bytes.
I suppose the correct way to convert the input hex string into byte array would be:
val input = "263e5df7a93ec5f5ea6ac215ed957c30"
val bytes = input.chunked(2).map { it.toInt(16).toByte() }.toByteArray()
Then you encode these bytes to base64 as usual.

Related

Convert Long to Base64 in Kotlin

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?
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.")
}

NumberFormatException in converting string to byte

I am trying to get the MD5 format of string
Code:
fun getEncodedData(data: String): String? {
val MD5 = "MD5"
// Create MD5 Hash
val digest = java.security.MessageDigest
.getInstance(MD5)
digest.update(data.toByte())
val messageDigest = digest.digest()
// Create Hex String
val hexString = StringBuilder()
for (aMessageDigest in messageDigest) {
var h = Integer.toHexString(0xFF and aMessageDigest.toInt())
while (h.length < 2)
h = "0$h"
hexString.append(h)
}
return hexString.toString()
}
There is a crash at: digest.update(data.toByte()). I get number format Exception
Input I am passing for data: oEXm43
There is no crash if I pass ex: 11 as a string for input data
Should the input always should be integer in the string or can it be a mixture of number and characters.
You're trying to call the update method that takes a single byte parameter, and using toByte which converts the entire string's numerical value to a single byte. This conversion method is what fails on non-numerical values inside a String.
Instead, you can use the variant of update with a byte[] parameter, and convert your String to an array of bytes (one per character) with toByteArray:
digest.update(data.toByteArray())

Declaring Byte in Kotlin does compile-time error 'The integer literal does not conform to the expected type Byte'

As seen another question in 0xFF0000FF An integer literal does not conform to the expected type kotlin.Int
I declaring value 0xFF as Byte
val b:Byte = 0xFF
receiving The integer literal does not conform to the expected type Byte compile error
Since I have clue about kotlin.Byte is signed byte
How to declaring Byte in Kotlin with 0x00 - 0xFF unsigned byte just like .net Byte b = 0xFF ?
.
.
If you want instant compiler for testing and answer:
rextester , try.kotlinlang.org
Kotlin doesn't automatically convert between number types.
If you do val b:Byte = 0xFF.toByte() then it compiles and results in a byte with value -1.
If you want to hold the unsigned byte value then you need to store it as a Char, but you will need to convert it to another type to print it as a number:
val b = 0xFF.toChar()
println(b.toInt())
Kotlin now supports unsigned integer types:
val b: UByte = 255u
val c: UByte = 0xFFu

What is the difference between two conversions from Long to ByteArray?

import java.lang.Long as JLong
import java.lang.Byte as JByte
import java.nio.ByteBuffer
fun Long.toByteArray1() =
ByteBuffer.allocate(JLong.SIZE / JByte.SIZE)
.putLong(this)
.array()
fun Long.toByteArray2() =
this.toString()
.toByteArray(Charsets.UTF_8)
fun main(args: Array<String>) {
val a1: ByteArray = 10L.toByteArray1()
val a2: ByteArray = 10L.toByteArray2()
println("a1 = ${a1.toString()}")
println("a1 = ${ByteBuffer.wrap(a1).getLong()}")
println("a2 = ${a2.toString()}")
println("a2 = ${String(a2, Charsets.UTF_8)}")
}
What is the difference between toByteArray1() and toByteArray2()?
If I send the bytes into the outputstream what receiver will get?
They are completely different.
.toByteArray1() returns bytes of the signed long number (therefore it should contain exactly 8 bytes = 64 bits):
println(0.toByteArray1().size) // 8
println(1234.toByteArray1().size) // 8
.toByteArray2() first converts the long to String and then to the byte array with the String characters encoded in UTF-8 (since there are only digits, they are encoded one byte each), and the byte array in this case contains the same number of bytes as the length of the string representation:
println(0.toByteArray2().size) // 1
println(-1234.toByteArray2().size) // 5
println(123456789012.toByteArray2().size) // 12
And, of course, the decoders should be different, as in your example where you decode a1 and a2.

How to convert String to Long in Kotlin?

So, due to lack of methods like Long.valueOf(String s) I am stuck.
How to convert String to Long in Kotlin?
1. string.toLong()
Parses the string as a [Long] number and returns the result.
#throws NumberFormatException if the string is not a valid
representation of a number.
2. string.toLongOrNull()
Parses the string as a [Long] number and returns the result or null
if the string is not a valid representation of a number.
3. string.toLong(10)
Parses the string as a [Long] number and returns the result.
#throws NumberFormatException if the string is not a valid
representation of a number.
#throws IllegalArgumentException when
[radix] is not a valid radix for string to number conversion.
public inline fun String.toLong(radix: Int): Long = java.lang.Long.parseLong(this, checkRadix(radix))
4. string.toLongOrNull(10)
Parses the string as a [Long] number and returns the result or null
if the string is not a valid representation of a number.
#throws IllegalArgumentException when [radix] is not a valid radix for string
to number conversion.
public fun String.toLongOrNull(radix: Int): Long? {...}
5. java.lang.Long.valueOf(string)
public static Long valueOf(String s) throws NumberFormatException
String has a corresponding extension method:
"10".toLong()
Extension methods are available for Strings to parse them into other primitive types. Examples below:
"true".toBoolean()
"10.0".toFloat()
"10.0".toDouble()
"10".toByte()
"10".toShort()
"10".toInt()
"10".toLong()
Note: Answers mentioning jet.String are outdated. Here is current Kotlin (1.0):
Any String in Kotlin already has an extension function you can call toLong(). Nothing special is needed, just use it.
All extension functions for String are documented. You can find others for standard lib in the api reference
Actually, 90% of the time you also need to check the 'long' is valid, so you need:
"10".toLongOrNull()
There is an 'orNull' equivalent for each 'toLong' of the basic types, and these allow for managing invalid cases with keeping with the Kotlin? idiom.
It's interesting. Code like this:
val num = java.lang.Long.valueOf("2");
println(num);
println(num is kotlin.Long);
makes this output:
2
true
I guess, Kotlin makes conversion from java.lang.Long and long primitive to kotlin.Long automatically in this case. So, it's solution, but I would be happy to see tool without java.lang package usage.
In Kotlin, to convert a String to Long (that represents a 64-bit signed integer) is simple.
You can use any of the following examples:
val number1: Long = "789".toLong()
println(number1) // 789
val number2: Long? = "404".toLongOrNull()
println("number = $number2") // number = 404
val number3: Long? = "Error404".toLongOrNull()
println("number = $number3") // number = null
val number4: Long? = "111".toLongOrNull(2) // binary
println("numberWithRadix(2) = $number4") // numberWithRadix(2) = 7
With toLongOrNull() method, you can use let { } scope function after ?. safe call operator.
Such a logic is good for executing a code block only with non-null values.
fun convertToLong(that: String) {
that.toLongOrNull()?.let {
println("Long value is $it")
}
}
convertToLong("123") // Long value is 123
One good old Java possibility what's not mentioned in the answers is java.lang.Long.decode(String).
Decimal Strings:
Kotlin's String.toLong() is equivalent to Java's Long.parseLong(String):
Parses the string argument as a signed decimal long. ... The
resulting long value is returned, exactly as if the argument and the
radix 10 were given as arguments to the parseLong(java.lang.String, int) method.
Non-decimal Strings:
Kotlin's String.toLong(radix: Int) is equivalent to Java's eLong.parseLong(String, int):
Parses the string argument as a signed long in the radix specified by
the second argument. The characters in the string must all be digits of the specified radix ...
And here comes java.lang.Long.decode(String) into the picture:
Decodes a String into a Long. Accepts decimal, hexadecimal, and octal
numbers given by the following grammar: DecodableString:
(Sign) DecimalNumeral | (Sign) 0x HexDigits | (Sign) 0X HexDigits | (Sign) # HexDigits | (Sign) 0 OctalDigits
Sign: - | +
That means that decode can parse Strings like "0x412", where other methods will result in a NumberFormatException.
val kotlin_toLong010 = "010".toLong() // 10 as parsed as decimal
val kotlin_toLong10 = "10".toLong() // 10 as parsed as decimal
val java_parseLong010 = java.lang.Long.parseLong("010") // 10 as parsed as decimal
val java_parseLong10 = java.lang.Long.parseLong("10") // 10 as parsed as decimal
val kotlin_toLong010Radix = "010".toLong(8) // 8 as "octal" parsing is forced
val kotlin_toLong10Radix = "10".toLong(8) // 8 as "octal" parsing is forced
val java_parseLong010Radix = java.lang.Long.parseLong("010", 8) // 8 as "octal" parsing is forced
val java_parseLong10Radix = java.lang.Long.parseLong("10", 8) // 8 as "octal" parsing is forced
val java_decode010 = java.lang.Long.decode("010") // 8 as 0 means "octal"
val java_decode10 = java.lang.Long.decode("10") // 10 as parsed as decimal
If you don't want to handle NumberFormatException while parsing
var someLongValue=string.toLongOrNull() ?: 0
Actually, there are several ways:
Given:
var numberString : String = "numberString"
// number is the Long value of numberString (if any)
var defaultValue : Long = defaultValue
Then we have:
+—————————————————————————————————————————————+——————————+———————————————————————+
| numberString is a valid number ? | true | false |
+—————————————————————————————————————————————+——————————+———————————————————————+
| numberString.toLong() | number | NumberFormatException |
+—————————————————————————————————————————————+——————————+———————————————————————+
| numberString.toLongOrNull() | number | null |
+—————————————————————————————————————————————+——————————+———————————————————————+
| numberString.toLongOrNull() ?: defaultValue | number | defaultValue |
+—————————————————————————————————————————————+——————————+———————————————————————+
string.toLong()
where string is your variable.