【问题标题】:ByteArray convert to String with UTF-8 charset in kotlin problemByteArray 在 kotlin 问题中使用 UTF-8 字符集转换为字符串
【发布时间】:2021-04-16 07:14:04
【问题描述】:

我有点迷茫

// 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()

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

【问题讨论】:

  • [-17, -65, -67] 数组(十六进制 0xEF,0xBF,0xBD)是字节顺序标记 (UTF-8)(在 latin1 中显示为 �)。
  • @JosefZ 不,那是0xEF,0xBB,0xBF
  • 我的错。实际上,[-17, -65, -67] 字节数组(十六进制 0xEF,0xBF,0xBD)在 latin1 中显示为 � 是 �U+FFFD 替换字符。谢谢@AlexeyRomanov:字节顺序标记不同:U+FEFF (hexa 0xEF,0xBB,0xBF, latin1 ) 零宽度无间断空间

标签: string kotlin utf-8 byte


【解决方案1】:

这里的问题是您的字节不是有效的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 in unsigned hex)不是有效的 UTF-8。

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

然后,当您将 that 转换回 UTF-8 时,您会得到替换字符的 UTF-8 编码,即EF BF BD。如果你把它解释为有符号字节,你会得到-17 -65 -67——就像问题一样。

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

【讨论】:

    猜你喜欢
    • 2018-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多