有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java将字符[]转换为字节[]

我想在Java中将字符数组转换为字节数组。进行这种转换有哪些方法


共 (6) 个答案

  1. # 1 楼答案

    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;
    }
    
  2. # 2 楼答案

    如果只想转换数据容器(数组)类型本身,只考虑数据大小,并且不知道任何编码:

    // original byte[]
    byte[] pattern = null;
    char[] arr = new char[pattern.length * 2];
    ByteBuffer wrapper = ByteBuffer.wrap(pattern);
    wrapper.position(0);
    int i = 0;
    while(wrapper.hasRemaining()) {
        char character = wrapper.remaining() < 2 ? ((char) (((int) wrapper.get()) << 8)) : wrapper.getChar();
        arr[i++] = character;
    }
    
  3. # 3 楼答案

    你可以做一个方法:

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

    希望这有帮助

  4. # 4 楼答案

    char[] ch = ?
    new String(ch).getBytes();
    

    或者

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

    获取非默认字符集

    更新:自Java 7:new String(ch).getBytes(StandardCharsets.UTF_8);

  5. # 5 楼答案

    转换而不创建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[]中。(见Why is char[] preferred over String for passwords?

    记住不要将敏感数据写入日志,并确保JVM不会包含任何对它的引用


    上面的代码是正确的,但不是有效的。如果你不需要性能,但想要安全,你可以使用它。如果安全也不是一个目标,那么只需String.getBytes。如果你看不起JDK中encode的实现,上面的代码是无效的。此外,还需要复制数组和创建缓冲区。另一种转换方法是内联所有代码隐藏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]中的代码非常相似

  6. # 6 楼答案

    编辑:Andrey的答案已更新,因此以下内容不再适用

    安德烈的回答(在撰写本文时投票率最高)略显保守 不准确的我本想加上这句话作为评论,但我不是 声誉很好

    在安德烈的回答中:

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