I would like to convert a character array to a byte array in Java. What methods exists for making this conversion?
Syntax: byte by = (byte) ch; Here, ch is the char variable to be converted into Byte. It tells the compiler to convert the char into its byte equivalent value.
You can simply iterate the byte array and print the byte using System. out. println() method.
To get the right point use char c = (char) (b & 0xFF) which first converts the byte value of b to the positive integer 200 by using a mask, zeroing the top 24 bits after conversion: 0xFFFFFFC8 becomes 0x000000C8 or the positive number 200 in decimals.
Convert without creating String
object:
import java.nio.CharBuffer; import java.nio.ByteBuffer; import java.util.Arrays; byte[] toBytes(char[] chars) { CharBuffer charBuffer = CharBuffer.wrap(chars); ByteBuffer byteBuffer = Charset.forName("UTF-8").encode(charBuffer); byte[] bytes = Arrays.copyOfRange(byteBuffer.array(), byteBuffer.position(), byteBuffer.limit()); Arrays.fill(byteBuffer.array(), (byte) 0); // clear sensitive data return bytes; }
Usage:
char[] chars = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; byte[] bytes = toBytes(chars); /* do something with chars/bytes */ Arrays.fill(chars, '\u0000'); // clear sensitive data Arrays.fill(bytes, (byte) 0); // clear sensitive data
Solution is inspired from Swing recommendation to store passwords in char[]. (See Why is char[] preferred over String for passwords?)
Remember not to write sensitive data to logs and ensure that JVM won't hold any references to it.
The code above is correct but not effective. If you don't need performance but want security you can use it. If security also not a goal then do simply String.getBytes
. Code above is not effective if you look down of implementation of encode
in JDK. Besides you need to copy arrays and create buffers. Another way to convert is inline all code behind encode
(example for UTF-8):
val xs: Array[Char] = "A ß € 嗨 𝄞 🙂".toArray val len = xs.length val ys: Array[Byte] = new Array(3 * len) // worst case var i = 0; var j = 0 // i for chars; j for bytes while (i < len) { // fill ys with bytes val c = xs(i) if (c < 0x80) { ys(j) = c.toByte i = i + 1 j = j + 1 } else if (c < 0x800) { ys(j) = (0xc0 | (c >> 6)).toByte ys(j + 1) = (0x80 | (c & 0x3f)).toByte i = i + 1 j = j + 2 } else if (Character.isHighSurrogate(c)) { if (len - i < 2) throw new Exception("overflow") val d = xs(i + 1) val uc: Int = if (Character.isLowSurrogate(d)) { Character.toCodePoint(c, d) } else { throw new Exception("malformed") } ys(j) = (0xf0 | ((uc >> 18))).toByte ys(j + 1) = (0x80 | ((uc >> 12) & 0x3f)).toByte ys(j + 2) = (0x80 | ((uc >> 6) & 0x3f)).toByte ys(j + 3) = (0x80 | (uc & 0x3f)).toByte i = i + 2 // 2 chars j = j + 4 } else if (Character.isLowSurrogate(c)) { throw new Exception("malformed") } else { ys(j) = (0xe0 | (c >> 12)).toByte ys(j + 1) = (0x80 | ((c >> 6) & 0x3f)).toByte ys(j + 2) = (0x80 | (c & 0x3f)).toByte i = i + 1 j = j + 3 } } // check println(new String(ys, 0, j, "UTF-8"))
Excuse me for using Scala language. If you have problems with converting this code to Java I can rewrite it. What about performance always check on real data (with JMH for example). This code looks very similar to what you can see in JDK[2] and Protobuf[3].
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With