Kotlin Android(API 29)UTF-8字符转换异常问题求助
问题描述
在Kotlin Android(API 29)中执行以下代码时,遇到字符串长度不符合预期的问题:
import kotlin.text.Charsets.UTF_8 var buf = byteArrayOf(0xF0.toByte(), 0xa9.toByte(), 0xbd.toByte(), 0xbe.toByte()) var s = String(buf, UTF_8) // 注:原代码中变量名s8应为s,属于笔误 Log.e(TAG, "buf len ${buf.size} as UTF-8 : <$s> len ${s.length}")
输出结果:
buf len 4 as UTF-8 : <𩽾> len 2
预期字符串长度应为1(对应UTF-8编码F0A9BDBE的字符𩽾),但实际返回长度为2,而Python中执行类似逻辑则无此问题。
原因解析
这不是Kotlin的字符串转换错误,而是Java/Kotlin中String.length()的定义和你预期的不一致:
- Java/Kotlin的
String内部采用UTF-16编码存储字符,length()方法返回的是UTF-16代码单元的数量,而非Unicode字符(码点)的数量。 - 字符𩽾的Unicode码点是
U+29F7E,属于Unicode辅助平面(U+10000至U+10FFFF),这类字符无法用单个UTF-16代码单元表示,需要两个UTF-16代码单元(称为"代理对")来存储,因此length()返回2。 - Python的字符串是基于Unicode码点实现的,
len()直接返回Unicode字符的数量,所以不会出现这个差异。
解决方法
如果需要获取实际的Unicode字符数量,使用String.codePointCount()方法:
val charCount = s.codePointCount(0, s.length) Log.e(TAG, "实际Unicode字符数:$charCount") // 输出:实际Unicode字符数:1
此外,若要遍历每个Unicode字符,避免按UTF-16代码单元遍历的问题,可以使用codePoints()方法:
s.codePoints().forEach { codePoint -> val char = String(Character.toChars(codePoint)) Log.e(TAG, "Unicode字符:$char") }
内容的提问来源于stack exchange,提问作者PST
相关产品推荐
相关产品推荐

