Преобразование символа [] в байт [] - PullRequest
72 голосов
/ 01 апреля 2011

Я хотел бы преобразовать массив символов в массив байтов в Java. Какие методы существуют для этого преобразования?

Ответы [ 6 ]

146 голосов
/ 12 марта 2012

Преобразование без создания 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 ].

69 голосов
/ 01 апреля 2011
char[] ch = ?
new String(ch).getBytes();

или

new String(ch).getBytes("UTF-8");

, чтобы получить кодировку не по умолчанию.

Обновление: Начиная с Java 7: new String(ch).getBytes(StandardCharsets.UTF_8);

18 голосов
/ 16 декабря 2013

Редактировать: ответ Андрея был обновлен, поэтому следующее больше не применяется.

Ответ Андрея (самый высокий голос за время написания) немного неверен. Я бы добавил это как комментарий, но я не Достойный авторитет.

В ответе Андрея:

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));
0 голосов
/ 16 апреля 2018
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;
}
0 голосов
/ 25 сентября 2014

Вы можете сделать метод:

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;
}

Надеюсь, это поможет

0 голосов
/ 01 апреля 2011

На самом деле char и byte могут иметь разный размер в Java, поскольку char может содержать любой символ Unicode, который может достигать 16 бит.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...