Преобразование без создания String
объекта:
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;
}
Использование:
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
Решение основано на рекомендации Swing хранить пароли в char [].(См. Почему char [] предпочтительнее, чем String для паролей? )
Не забудьте не записывать конфиденциальные данные в журналы и убедитесь, что JVM не будет содержать никаких ссылок на них.
Код выше верен, но не эффективен.Если вам не нужна производительность, но вам нужна безопасность, вы можете использовать ее.Если безопасность тоже не цель, просто сделайте String.getBytes
.Код выше не эффективен, если вы посмотрите вниз на реализацию encode
в JDK.Кроме того, вам нужно копировать массивы и создавать буферы.Еще один способ конвертации - встроенный весь код encode
(пример для 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"))
Извините за использование языка Scala.Если у вас есть проблемы с преобразованием этого кода в Java, я могу переписать его.Что касается производительности, всегда проверяйте реальные данные (например, с помощью JMH).Этот код выглядит очень похоже на то, что вы можете увидеть в JDK [ 2 ] и Protobuf [ 3 ].