我必须存储大量的布尔值,我选择将它们作为字节数组存储为字符串。但我无法理解,为什么转换为字符串和返回会产生不同的字符串值:
支持方法:
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 1110 1111 0000 0001
对我来说,它看起来不像[0,15]索引或[1,-128]:)
这怎么可能发生?我怀疑“1000 0000 0000 0001”中的最后一个“1”,可能会导致这个问题,但我仍然不知道答案。
感谢。
P.S。在问题中添加了java
标记,因为我认为kotlin和java的答案都是一样的。
答案 0 :(得分:3)
这里是您的问题的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&#34;�&#34;。
您可以将字符串编码和解码为ISO-8859-1 aka Latin1,因为所有字节字符串在ISO-8859编码系列中都有效。 ISO-8859-1具有方便的属性,即每个字节值直接对应于相同的unicode代码点,因此0x80
编码为U + 0080,0xFF
编码为U + 00FF等。