如何以二进制写入UTF-8字符串?解决epub双重编码报错问题
解决双重UTF-8编码文件修复时的“wide character in subroutine”错误
你遇到的这个错误,核心原因是Perl严格区分字节字符串和字符字符串:当你尝试写入包含宽字符的字符字符串时,若未明确指定二进制模式,Perl会触发该错误。结合你的场景,问题出在文件读写模式和编码处理的顺序上,以下是具体解决方案:
正确处理代码
use Mojo::Base -strict; use Mojo::File; use Encode qw(decode_utf8 encode_utf8); # 二进制模式读取原始文件,获取未被自动解码的双重编码字节流 my $raw_bytes = Mojo::File->new('part0000.html')->slurp({mode => '<:raw'}); # 对字节流做一次UTF-8解码,得到正常的字符(解决双重编码问题) my $correct_chars = decode_utf8($raw_bytes); # 将字符重新编码为UTF-8字节流 my $fixed_bytes = encode_utf8($correct_chars); # 二进制模式写入文件,避免Perl自动编码导致的宽字符错误 Mojo::File->new('fixed.html')->spurt($fixed_bytes, {mode => '>:raw'});
错误原因分析
- 未指定二进制读写模式:默认的
slurp()和spurt()会用文本模式处理,Perl会自动尝试将字节解码为字符,这会破坏你需要处理的双重编码字节流,后续的解码/编码操作就会混乱。 - 错误的编码操作顺序:之前的代码中,若
slurp()已经自动解码了字节流,再调用decode_utf8相当于对字符做二次解码,生成的字符串会包含无效的宽字符,写入时自然触发错误。 utf8::downgrade的局限性:这个函数只能将纯ASCII的字符字符串转为字节字符串,一旦存在中文、日文等宽字符,直接调用会失败,无法解决根本问题。
内容的提问来源于stack exchange,提问作者shirha
相关产品推荐
相关产品推荐

