Я хотел бы преобразовать массив символов в массив байтов в Java. Какие существуют методы для этого преобразования?
java
arrays
type-conversion
Арун Абрахам
источник
источник
Преобразовать без создания
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 ].
источник
Изменить: ответ Андрея был обновлен, поэтому следующее больше не применяется.
Ответ Андрея (наибольшее количество голосов на момент написания) несколько неверен. Я бы добавил это в качестве комментария, но я недостаточно уважаемый.
В ответ Андрея:
char[] chars = {'c', 'h', 'a', 'r', 's'} byte[] bytes = Charset.forName("UTF-8").encode(CharBuffer.wrap(chars)).array();
вызов array () может не вернуть желаемое значение, например:
char[] c = "aaaaaaaaaa".toCharArray(); System.out.println(Arrays.toString(Charset.forName("UTF-8").encode(CharBuffer.wrap(c)).array()));
вывод:
[97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 0]
Как видно, добавлен нулевой байт. Чтобы избежать этого, используйте следующее:
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));
вывод:
[97, 97, 97, 97, 97, 97, 97, 97, 97, 97]
Поскольку в ответе также упоминается использование паролей, возможно, стоит очистить массив, который поддерживает ByteBuffer (доступный через функцию 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()
вернет что-либо, кроме 1 (я получаю 1.1). Из интереса, какую ОС / арку вы используете, поскольку я дважды проверил с помощью oracle 1.7.0_51 и openjdk 1.7.0_51 и обнаружил, что он сломан с 10 символами.buffer.array()
вtoBytes
функции все еще нужно переопределить, в настоящее время только копия.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; }
источник
Вы можете сделать метод:
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; }
Надеюсь это поможет
источник