提问人:choeger 提问时间:6/9/2023 更新时间:6/9/2023 访问量:78
'use utf8' 对 'Encode' 有什么影响?
What is the influence of `use utf8` on `Encode`?
问:
因此,我正在我们的 DB 例程中寻找一个宽字符问题,并偶然发现了以下奇怪之处:
use utf8;
use Encode;
my $x = "ö";
my $decoded = Encode::decode('UTF-8', $x);
my $encoded = Encode::encode('UTF-8', $decoded);
my $redecoded = Encode::decode('UTF-8', $encoded);
{
use bytes;
printf "original: %vx\n", $x;
printf "decoded: %vx\n", $decoded;
printf "encoded: %vx\n", $encoded;
printf "redecoded: %vx\n", $redecoded;
}
执行此脚本可提供:
original: c3.b6
decoded: ef.bf.bd
encoded: ef.bf.bd
redecoded: ef.bf.bd
我不认为0xef 0xbf 0xbd是有效的UTF-8。如果我删除该语句,则输出如下:use utf8
original: c3.b6
decoded: c3.b6
encoded: c3.b6
redecoded: c3.b6
那么为什么要改变解码语义呢?use utf8;
答:
use utf8
告诉 Perl 使用 UTF-8 而不是 ASCII 解码脚本。它对 Encode 没有影响。你得到不同的结果,因为你将不同的字符串传递给 。decode
由于错误地使用了 ,您没有注意到这一点。(需要明确的是,使用总是不正确的。让我们删除它并再次运行您的程序。use bytes;
use bytes;
具体来说,我将使用以下内容:
printf "original: %vx\n", $x;
printf "decode('UTF-8', %vx): %vx\n", $x, $decoded;
printf "encode('UTF-8', %vx): %vx\n", $decoded, $encoded;
printf "decode('UTF-8', %vx): %vx\n", $encoded, $redecoded;
跟:use utf8;
original: f6
decode('UTF-8', f6): fffd
encode('UTF-8', fffd): ef.bf.bd
decode('UTF-8', ef.bf.bd): fffd
使用 ,Perl 期望您的程序使用 UTF-8 进行编码,因此您的程序具有等效的 .换句话说,字符串包含一个值为 0xf6 的字符。这不是有效的 UTF-8,因此当您将其传递给 时,您会得到垃圾(U+FFFD 替换字符)。use utf8;
my $x = "\N{LATIN SMALL LETTER O WITH DIAERESIS}";
decode 'UTF-8'
替换为 以获得预期结果。my $decoded = Encode::decode('UTF-8', $x);
my $decoded = $x;
original: f6
decoded: f6
encode('UTF-8', f6): c3.b6
decode('UTF-8', c3.b6): f6
没有:use utf8;
original: c3.b6
decode('UTF-8', c3.b6): f6
encode('UTF-8', f6): c3.b6
decode('UTF-8', c3.b6): f6
如果没有 ,Perl 希望您的程序使用 ASCII 进行编码。它不可能包含,因为它不是 ASCII 字符。相反,您有等效的 (因为字符串文字是“8 位干净的”)。这是有效的 UTF-8,因此可以解码。use utf8;
ö
my $x = "\xc3\xb6";
评论
ef.bf.bd
是 UTF-8 字节,用于 (U+FFFD,替换字符)。你以一种奇怪的方式使用方法:是字符串到八位字节,而八位字节是字符串......perldoc.perl.org/Encode#THE-PERL-ENCODING-API�
Encode
Encode::encode
Encode::decode