'use utf8' 对 'Encode' 有什么影响?

What is the influence of `use utf8` on `Encode`?

提问人:choeger 提问时间:6/9/2023 更新时间:6/9/2023 访问量:78

问:

因此,我正在我们的 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;

Perl Unicode 编码 UTF-8

评论

2赞 JosefZ 6/9/2023
ef.bf.bd是 UTF-8 字节,用于 (U+FFFD,替换字符)。你以一种奇怪的方式使用方法:是字符串到八位字节,而八位字节是字符串......perldoc.perl.org/Encode#THE-PERL-ENCODING-APIEncodeEncode::encodeEncode::decode

答:

3赞 ikegami 6/9/2023 #1

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";