You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 15:47:06