Ich möchte ein Zeichenarray in ein Bytearray in Java konvertieren. Welche Methoden gibt es für diese Konvertierung?
Ich möchte ein Zeichenarray in ein Bytearray in Java konvertieren. Welche Methoden gibt es für diese Konvertierung?
Antworten:
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 StringObjekt 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;
}
Verwendung:
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 Empfehlung von Swing, Passwörter in char [] zu speichern. (Siehe Warum wird char [] für Passwörter gegenüber String bevorzugt? )
Denken Sie daran, keine vertraulichen Daten in Protokolle zu schreiben und sicherzustellen, dass JVM keine Verweise darauf enthält.
Der obige Code ist korrekt, aber nicht wirksam. Wenn Sie keine Leistung benötigen, aber Sicherheit wünschen, können Sie diese verwenden. Wenn Sicherheit auch kein Ziel ist, dann einfach tun String.getBytes. Der obige Code ist nicht wirksam, wenn Sie sich die Implementierung encodein JDK ansehen . Außerdem müssen Sie Arrays kopieren und Puffer erstellen. Eine andere Möglichkeit zum Konvertieren besteht darin, den gesamten Code inline zu integrieren 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 ich die Scala-Sprache verwende. Wenn Sie Probleme beim Konvertieren dieses Codes in Java haben, kann ich ihn neu schreiben. Was ist mit der Leistung? Überprüfen Sie immer die realen Daten (z. B. mit JMH). Dieser Code sieht dem in JDK [ 2 ] und Protobuf [ 3 ] sehr ähnlich .
Andreys Antwort (die höchste, die zum Zeitpunkt des Schreibens gewählt wurde) ist leicht falsch. Ich hätte dies als Kommentar hinzugefügt, aber ich bin nicht seriös genug.
In Andreys Antwort:
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, zum 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 Passwörtern anspielte, kann es sinnvoll sein, 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));
averageBytesPerChar()etwas anderes als 1 zurückgegeben wird (ich erhalte 1.1). Aus Interesse, welches Betriebssystem / welchen Arch Sie verwenden, habe ich mit Oracle 1.7.0_51 und openjdk 1.7.0_51 doppelt überprüft und festgestellt, dass es mit 10 Zeichen defekt ist.
buffer.array()in der toBytesFunktion noch überschrieben werden muss, derzeit nur die Kopie.
Sie könnten eine Methode machen:
public byte[] toBytes(char[] data) {
byte[] toRet = new byte[data.length];
for(int i = 0; i < toRet.length; i++) {
toRet[i] = (byte) data[i];
}
return toRet;
}
Hoffe das hilft