将Bytearray转换为字符串和背部产生不同的字符串



我必须存储大量布尔值列表,我选择将它们作为字节数组作为字符串存储。但是我不明白,为什么转换为字符串和后背产生不同的字符串值:

支持方法:

  fun ByteArray.string(): String {
    var str = ""
    this.reversed().forEach {
      str += intToString(it, 4)
    }
    return str
  }
  fun intToString(number: Byte, groupSize: Int): String {
    val result = StringBuilder()
    for (i in 7 downTo 0) {
      val mask = 1 shl i
      result.append(if (number.toInt() and mask != 0) "1" else "0")
      if (i % groupSize == 0)
        result.append(" ")
    }
    result.replace(result.length - 1, result.length, "")
    return result.toString()
  }

第一个示例:

给定选定的索引[0,14]我的代码转换为:as Bytes:[1,64]。.string()生产:

0100 0000 0000 0001

将其转换为字符串和返回:

array.toString(Charsets.UTF_8).toByteArray(Charsets.UTF_8)

结果:[1,64],.string()产生:

0100 0000 0000 0001

第二个示例:

给定选定的索引[0,15]我的代码转换为:as Bytes:[1,-128]。.string()生产:

1000 0000 0000 0001

这似乎很合法。现在将其转换为字符串

它产生4个字节的数组:[1,-17,-65,-67],.string()产生:

1011 1101 1011 1111 1111 1111 0000 0001

对我来说看起来不像[0,15]索引或[1,-128]:(

这怎么会发生?我怀疑" 1000 0000 0000 0001"中的最后一个" 1",可能会导致此问题,但我仍然不知道答案。

谢谢。

P.S。在问题中添加了java标签,因为我认为Kotlin和Java的答案都是相同的。

这是您问题的MCVE(在Java中(:

import java.nio.charset.*;
class Test {
  public static void main(String[] args) {
    byte[] array = { -128 };
    byte[] convertedArray = new String(array, StandardCharsets.UTF_8).getBytes(StandardCharsets.UTF_8);
    for(int i=0; i<convertedArray.length; i++) {
      System.out.println(convertedArray[i]);
    }
  }
}

预期输出:

-128

实际输出:

-17
-65
-67

这是因为字节-128不是有效的UTF-8字符,因此它被Unicode替换字符u fffd"。"。

替换。

您可以用ISO-8859-1(aka Latin1(编码并将字符串解码,因为所有字节字符串在ISO-8859的编码家族中都是有效的。ISO-8859-1具有每个字节值直接对应于同一Unicode代码点的方便属性,因此0x80编码为U 0080,0xFF为U 00FF等。

最新更新