ByteArray 在 kotlin 问题中使用 UTF-8 字符集转换为字符串

ByteArray convert to String with UTF-8 charset in kotlin problem

有点迷茫

// default charset utf8
val bytes = byteArrayOf(78, 23, 41, 51, -32, 42)
val str = String(bytes)
// there i got array [78, 23, 41, 51, -17, -65, -67, 42]
val weird = str.toByteArray()

出于某种原因,我将随机值放入字节 属性。为什么不一致???

这里的问题是您的字节不是有效的 UTF-8 序列。

例如,任何字节序列都可以解释为有效 ISO Latin-1。 (值 0–31 的字节可能存在问题,但这些通常不会停止存储和处理字符。)类似地适用于大多数其他 8 位字符集。

但 UTF-8 并非如此。虽然 1-127 范围内的所有字节序列都是有效的 UTF-8(并且与它们在 ASCII 和大多数 8 位编码中的解释相同),但 128-255 范围内的字节只能出现在某些 well-defined combinations. (这有几个非常有用的特性:它可以让您以很高的概率识别 UTF-8;它还避免了同步、搜索、排序等方面的问题)

在这种情况下,问题中的序列(无符号十六进制的 4E 17 29 33 E0 2A)不是有效的 UTF-8。

因此,当您尝试使用默认编码 (UTF-8) 将其转换为字符串时,JVM 会替换 replacement character — 值 U+FFFD,如下所示: — 代替每个无效字符。

然后,当你将那个转换回UTF-8时,你得到替换字符的UTF-8编码,即EF BF BD。如果您将其解释为带符号的字节,您将得到 -17 -65 -67 — 如问题中所述。

所以 Kotlin/JVM 正在尽其所能处理无效输入。