为何读取文件句柄时'utf8-c8'编码无法正常工作?
解决Raku中文件句柄读取代理码点UTF-8序列报错的问题
问题核心
读取包含无效UTF-8字节序列(如高代理码点U+D83F对应的0xED 0xA0 0xBF)的文件时,直接使用slurp $path, :encoding<utf8-c8>可正常解码为Raku字符串,但通过文件句柄设置:encoding<utf8-c8>后读取,会触发“无法编码Unicode代理码点”的错误,环境为Fedora 36、Rakudo v2022.07。
解决方案
方法1:二进制读取后手动解码
绕开文件句柄编码的潜在问题,先以二进制模式读取原始字节,再显式用utf8-c8解码:
# 二进制模式打开文件 my $fh = open 'testfile', :bin; # 读取所有字节 my $raw-bytes = $fh.read-all; # 用utf8-c8解码为字符串 my $str = $raw-bytes.decode('utf8-c8'); $fh.close; # 验证结果 say $str.ord; # 输出55359(对应U+D83F的十进制值) say $str.chars; # 输出1
方法2:修正文件句柄的打开参数
若坚持使用文本模式打开,确保编码参数正确传递(部分旧版本Rakudo需显式指定读取模式):
my $fh = open 'testfile', :read, :encoding<utf8-c8>; my $str = $fh.slurp; $fh.close;
原因说明
在Rakudo v2022.07版本中,open函数的:encoding参数对utf8-c8编码的处理存在兼容性问题,无法正确识别并解码代理码点对应的UTF-8字节序列。而slurp函数直接调用底层解码逻辑,不存在此问题。通过二进制读取后手动解码,可确保所有字节序列(包括代理码点对应的无效UTF-8)都被utf8-c8正确转换为Raku字符串。
测试文件生成
可通过以下Linux命令生成包含目标字节序列的测试文件:
echo -n -e '\xed\xa0\xbf' > testfile
内容的提问来源于stack exchange,提问作者Robin A. Meade
相关产品推荐
相关产品推荐

