Dart中codeUnits属性与utf8.encode函数的区别及解码相关疑问
问题解答
1. 直接使用utf8.decode解码encoded2是否合理?
不合理,当前示例运行正常仅为特殊场景下的巧合。
原因解释
Dart字符串的codeUnits属性返回的是UTF-16编码单元的列表:
- 当字符串内所有字符都属于ASCII范围(码点U+0000 ~ U+007F)时,每个UTF-16编码单元的数值和UTF-8对该字符的单字节编码数值完全一致,所以示例中两次base64编码结果相同,用
utf8.decode解码也能得到正确结果。 - 一旦字符串包含中文、emoji、特殊西欧字符等超出ASCII范围的内容,UTF-16编码单元的数值会大于127,此时直接将
codeUnits传入base64Encode得到的encoded2,对应的字节序列完全不符合UTF-8编码规则,用utf8.decode解码会直接抛出格式错误,或得到无法识别的乱码。
2. encoded2的正确解码方式
首先需要注意:你当前生成encoded2的编码逻辑本身存在局限性——base64Encode要求输入为0~255范围的单字节列表,而UTF-16编码单元是16位整数,超出单字节范围的高位信息会被直接截断,仅能正常处理全ASCII的字符串。
对应该编码逻辑的解码不需要经过utf8.decode,直接用String.fromCharCodes处理base64解码结果即可:
var decoded2 = String.fromCharCodes(base64Decode(encoded2));
如果需要兼容全字符集的UTF-16编码base64转换,编码阶段需要先将UTF-16编码单元序列按大小端规则转换为规范的双字节序列,再做base64编码;解码阶段反向将base64解码得到的字节序列拼接回UTF-16编码单元后,再调用String.fromCharCodes生成字符串即可。
内容的提问来源于stack exchange,提问作者Ουιλιαμ Αρκευα
相关产品推荐
相关产品推荐

