Perl使用printf/sprintf对齐UTF-8字符串写入文件乱码如何解决?
问题原因
你遇到的是典型的UTF-8双重编码问题,根源是文件输出层重复设置了UTF-8编码规则:
- 打开文件时已经指定了
:encoding(UTF-8)层,会自动将Perl内部Unicode字符串转为UTF-8字节写入 - 后续添加的
binmode($out,':utf8')相当于把已经转好的UTF-8字节当成Unicode字符再次做UTF-8编码,最终就出现了ТеÑÑ这类乱码
小提示:如果你开启
use locale是为了适配本地化排序、格式化能力,请确保运行脚本的系统环境locale为UTF-8格式(例如ru_RU.UTF-8),非UTF-8的locale也可能引发字符解析异常。
修复步骤
删除冗余的binmode代码
直接移除你后续添加的binmode($out,':utf8');一行即可解决90%的情况。确认输入流编码处理正确
正则匹配用的$_如果来自外部输入(文件、接口、管道等),必须给输入流也指定UTF-8编码层,确保读入的内容被正确解析为Perl内部Unicode字符串,示例:# 读输入文件时指定编码层 open my $in, '<:encoding(UTF-8)', "input.json" or die $!;(可选)全局统一编码设置
可以在脚本开头的use声明区添加一行,统一所有文件、标准输入输出的默认编码为UTF-8,避免逐个设置遗漏:use open qw(:std :encoding(UTF-8));(可选)优化宽字符对齐效果
原生Perl的sprintf按字节计算字符串长度,处理西里尔文、中文等多字节字符时会出现对齐错位,可以使用Unicode::GCString模块计算字符的可视宽度,再手动补空格实现精准对齐。
内容的提问来源于stack exchange,提问作者alex2020
相关产品推荐
相关产品推荐

