Python String to Java byte[] - jython

From what I have understood, A Python 2 string (type str) is nothing but a sequence of bytes. How do I convert such a string to a Java byte array, explicit?
A naive attempt that doesn't work:
from jarray import array
myStr = 'some str object'
myJavaArr = array(myStr, 'b') # TypeError: Type not compatible with array type
My reason to this is that when Jython implicitly converts a Python String to Java code, it converts it to a Java String, incorrectly because it doesn't know the encoding of the str.

I found an utility method that does the trick:
from org.python.core.util import StringUtil
myJavaArr = StringUtil.toBytes(myStr)

Your original approach of passing a str object to jarray.array() worked in Jython 2.5 and earlier.
Now you must convert the str to a sequence of numbers first (eg list, tuple, or bytearray):
myStr = 'some str object'
myJavaArr = array( bytearray(myStr), 'b')
or
myStr = 'some str object'
myList = [ord(ch) for ch in myStr]
myJavaArr = array( myList, 'b')
(see also https://sourceforge.net/p/jython/mailman/message/35003179/)
Note, too, that Java's byte type is signed. The conversion will fail if any of your integers have a value outside the range -128..127. If you are starting with unsigned byte values in Python, you'll need to convert them. (eg apply this to each value: if 0x80 <= i <= 0xFF: i = i - 256)

Related

How to initialize and use charArray in Kotlin

I have this code
var str : CharArray
var t =0
for (k in i..i+3) {
str[t++] = array[k][j]
and it says str must be initialized, i don't know how to initialize.
I tried to initialize like this, but it says type mismatch,
var array: Array<CharArray> = arrayOf("India");
Type inference failed. Expected type mismatch:
required:
Array
found:
Array
You can initialize it this way:
var str : CharArray = CharArray(3) //if you know size
var str : CharArray = charArrayOf() //creates empty array
var str : CharArray? = null //makes your array nullable
Or you can use lateinit for initializing later
There are many ways to initialize arrays in Kotlin. The easiest, if all values are the same (here I'm using blanks), is this:
var chars = CharArray(26) { ' ' }
If you have a specific set of characters (here I made it a constant), I found this to be an easy way:
val CHARS = "abcdefghijklmnopqrstuvwxyz".toCharArray()
If you want to copy one to another (clone), you can do this:
val array2 = CharArray(array.size) { i -> array[i] }
In the example you gave above, you're trying to initialize an array of CharArray. Not sure if that's what you really want, but you can do it this way (I have an array of 25 items, each of which is an array with 5 blanks):
var array2D = Array<CharArray>(25) { CharArray(5) { ' ' } }
You have declared a variable of type CharArray, but haven't assigned it with any instance.
Before you can set elements of that CharArray, you have to create an instance of CharArray. It looks like you know the size of that array in advance, then you can use the following array constructor:
// creates an instance of CharArray of 4 elements, filled with \u0000 chars
val str = CharArray(4)
// after that you can set elements in the array
Bonus point: if you have a function that can provide an array element value given its index you can use the similar constructor to create instance and initialized its elements at once:
val str = CharArray(4) { index ->
array[i + index][j]
}
I found this question interesting and I wanna add my answer since i was solving similar leetcode problem;
var charArray: CharArray = charArrayOf('I', 'n', 'd', 'i', 'a')
var array: Array<CharArray> = arrayOf(
charArrayOf('I', 'n', 'd', 'i', 'a'),
charArrayOf('P', 'h', 'i', 'l', 'i', 'p', 'p', 'i', 'n', 'e', 's'),
)
I hope this help someone since i was just transitioning from Java to Kotlin ;)
If you declare your CharArray as it, you must initialize it immediately. Otherwise you can specify that you will initialized it later with the property lateinit, or you can declare your variable as a CharArray and set it to null, or you can use a
var str : CharArray? = null
var lateinit str: CharArray
it says str must be initialized. The problem is that you did not completely define the structure of the char array you intend to create. The CharArray requires knowing the actual length or size of the array you're creating. So in this note, you need to initialize it before trying to populate it. my code snippet is down
.....Your code still has some issues with it.
var str : CharArray = CharArray(9)
var t = 0
for (k in 1..9) {
str[t] = k
}
The output::: values from 1 to 30 will be stored in the str character array

Convert Hex value to Base64 using 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.

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())

Why single char and "single char String" not equal when converted to long (.toLong())

I wanted to sum the digits of Long variable and add it to the variable it self, I came with the next working code:
private fun Long.sumDigits(): Long {
var n = this
this.toString().forEach { n += it.toString().toLong() }
return n
}
Usage: assert(48.toLong() == 42.toLong().sumDigits())
I had to use it.toString() in order to get it work, so I came with the next test and I don't get it's results:
#Test
fun toLongEquality() {
println("'4' as Long = " + '4'.toLong())
println("\"4\" as Long = " + "4".toLong())
println("\"42\" as Long = " + "42".toLong())
assert('4'.toString().toLong() == 4.toLong())
}
Output:
'4' as Long = 52
"4" as Long = 4
"42" as Long = 42
Is it a good practice to use char.toString().toLong() or there is a better way to convert char to Long?
Does "4" represented by chars? Why it is not equal to it char representation?
From the documentation:
class Char : Comparable (source) Represents a 16-bit Unicode
character. On the JVM, non-nullable values of this type are
represented as values of the primitive type char.
fun toLong(): Long
Returns the value of this character as a Long.
When you use '4' as Long you actually get the Unicode (ASCII) code of the char '4'
As mTak says, Char represents a Unicode value. If you are using Kotlin on the JVM, you can define your function as follows:
private fun Long.sumDigits() = this.toString().map(Character::getNumericValue).sum().toLong()
There's no reason to return Long rather than Int, but I've kept it the same as in your question.
Non-JVM versions of Kotlin don't have the Character class; use map {it - '0'} instead.

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