Ich möchte ein Zeichen-Array in ein Byte-Array in Java konvertieren. Welche Methoden gibt es für diese Konvertierung?
char[] ch = ?
new String(ch).getBytes();
oder
new String(ch).getBytes("UTF-8");
um einen nicht standardmäßigen Zeichensatz zu erhalten.
Update: Seit Java 7: new String(ch).getBytes(StandardCharsets.UTF_8);
Konvertieren ohne String
-Objekt zu erstellen:
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;
}
Verwendungszweck:
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
Die Lösung basiert auf der Swing-Empfehlung zum Speichern von Kennwörtern in char []. (Siehe Warum wird char [] String für Kennwörter vorgezogen? )
Denken Sie daran, keine sensiblen Daten in die Protokolle zu schreiben, und stellen Sie sicher, dass die JVM keine Verweise darauf enthält.
Der obige Code ist korrekt, aber nicht effektiv. Wenn Sie keine Leistung benötigen, aber Sicherheit wünschen, können Sie sie verwenden. Wenn Sicherheit auch kein Ziel ist, dann String.getBytes
. Code oben ist nicht wirksam, wenn Sie von der Implementierung von encode
in JDK nach unten schauen. Außerdem müssen Sie Arrays kopieren und Puffer erstellen. Eine andere Möglichkeit zum Konvertieren ist der Inline-Code für encode
(Beispiel für 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"))
Entschuldigen Sie, dass Sie Scala-Sprache verwenden. Wenn Sie Probleme bei der Konvertierung dieses Codes in Java haben, kann ich ihn umschreiben. Was ist mit der Leistung? Überprüfen Sie immer auf realen Daten (zum Beispiel mit JMH). Dieser Code sieht sehr ähnlich aus wie in JDK [ 2 ] und Protobuf [ 3 ].
Die Antwort von Andrey (die höchste Stimme zum Zeitpunkt des Schreibens) ist leicht falsch. Ich hätte dies als Kommentar hinzugefügt, aber ich bin nicht seriös genug.
In der Antwort von Andrey:
char[] chars = {'c', 'h', 'a', 'r', 's'}
byte[] bytes = Charset.forName("UTF-8").encode(CharBuffer.wrap(chars)).array();
der Aufruf von array () gibt möglicherweise nicht den gewünschten Wert zurück. Beispiel:
char[] c = "aaaaaaaaaa".toCharArray();
System.out.println(Arrays.toString(Charset.forName("UTF-8").encode(CharBuffer.wrap(c)).array()));
ausgabe:
[97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 0]
Wie zu sehen ist, wurde ein Null-Byte hinzugefügt. Um dies zu vermeiden, verwenden Sie Folgendes:
char[] c = "aaaaaaaaaa".toCharArray();
ByteBuffer bb = Charset.forName("UTF-8").encode(CharBuffer.wrap(c));
byte[] b = new byte[bb.remaining()];
bb.get(b);
System.out.println(Arrays.toString(b));
ausgabe:
[97, 97, 97, 97, 97, 97, 97, 97, 97, 97]
Da die Antwort auch auf die Verwendung von Kennwörtern anspielt, kann es sich lohnen, Das Array auszublenden, das den ByteBuffer unterstützt (Zugriff über die Funktion Array ()):
ByteBuffer bb = Charset.forName("UTF-8").encode(CharBuffer.wrap(c));
byte[] b = new byte[bb.remaining()];
bb.get(b);
blankOutByteArray(bb.array());
System.out.println(Arrays.toString(b));
private static byte[] charArrayToByteArray(char[] c_array) {
byte[] b_array = new byte[c_array.length];
for(int i= 0; i < c_array.length; i++) {
b_array[i] = (byte)(0xFF & (int)c_array[i]);
}
return b_array;
}