Kotlin中从蓝牙设备字节数组提取指定长度字符串时无法去除末尾零值的技术问询
解决蓝牙字节数组转字符串时的空字节截断问题
刚接触Kotlin遇到这种小坑很正常,毕竟C系语言里处理以\0结尾的字符串是直觉操作,但Kotlin的数组和字符串API逻辑略有不同,咱们来拆解下问题和解决方案:
你原来代码的问题根源
你之前的思路是对的——找到第一个空字节就停止复制,但tempBytes是一个30字节的新数组,默认所有元素都是0。你只填充了前index个有效字节,剩下的20+个字节还是0,转字符串的时候会把整个30字节都转换成字符(那些0对应的就是你看到的乱码��������������������)。之后用dropLast(20 - index)也没用,因为总长度是30,你要去掉的是30 - index个字符,而不是20 - index,这就导致没删干净后面的空字节对应的乱码。
更简洁高效的解决方案
其实不用额外复制数组,直接利用Kotlin的API找到第一个空字节的位置,然后截取有效区间的字节生成字符串就行,完美对应C系语言里的字符串截断逻辑:
val bytes = job.characteristic.value // 定位第一个空字节的位置 val nullPosition = bytes.indexOf(0) // 确定有效字符串的长度: // - 如果没找到空字节,或者空字节在预留的20字节之外,就取满20字节 // - 否则取到第一个空字节的位置 val validLength = when { nullPosition == -1 || nullPosition > 20 -> 20 else -> nullPosition } // 直接截取有效字节生成字符串,指定字符集(比如你需要的UTF_8或US_ASCII) val deviceID = String(bytes, 0, validLength, Charsets.UTF_8) Log.i("BleDeviceVM", "Received deviceID: $deviceID")
补充说明
你后来想到的代码思路是完全正确的!上面的写法只是把边界判断用when整理得更清晰,核心都是找到第一个\0的位置,然后只转换该位置之前的有效字节。Kotlin的String构造函数支持指定起始索引和长度,直接跳过后面的空字节,自然就不会出现乱码了。
内容的提问来源于stack exchange,提问作者user3244148
相关产品推荐
相关产品推荐

