为什么binmode作为原始产生变音符号?可以详细说明苏黎世'字符串存储在Perl内部?只是有点失落。
use strict;
use warnings;
my $filename = "result-test-encoding-raw.xml";
open(my $fh,'>', $filename) or die "die";
#binmode $fh, ':utf8'; #bad umlaut
binmode $fh, ':raw'; #good umlaut
print $fh '<?xml version="1.0" encoding="UTF-8"?>';
print $fh '<node>';
my $line_text = 'Zürich';
print $fh $line_text;
print $fh ' next ';
$line_text = 'Zürich';
print $fh $line_text;
print $fh '</node>';
close($fh);
答案 0 :(得分:4)
您错过了use utf8;
,它告诉Perl您的源代码是使用UTF-8编码的。
默认情况下,源文件应使用US-ASCII进行编码。
如果您使用UTF-8对源文件进行编码,但是您没有告诉Perl(使用use utf8;
),Perl会将其视为使用US-ASCII进行编码。对于字符串文字,Perl只是将字节映射到字符串字符(而不是拒绝非ASCII字符)。这意味着$line_text
包含5A.C3.BC.72.69.63.68
。
当您将这些字符传递给带有编码层的文件句柄时,编码层会将这些字符视为Unicode代码点(Zürich
)并生成相应的字节来表示这些字符。
如果您使用UTF-8对源文件进行编码,并且如果您将其告知Perl(使用use utf8;
),则Perl会将其视为使用UTF-8进行编码(相应地对其进行解码)。这意味着$line_text
包含5A.FC.72.69.63.68
。
当您将这些字符传递给带有编码层的文件句柄时,编码层会将这些字符视为Unicode代码点(Zürich
)并生成相应的字节来表示这些字符。
use strict;
use warnings;
use utf8; # Source code is encoded using UTF-8.
use open ':std', ':encoding(UTF-8)'; # Terminal expects UTF-8. Default encoding for files.
my $filename = "result-test-encoding-raw.xml";
open(my $fh, '>', $filename)
or die("Can't create \"$filename\": $!\n");
...
print $fh 'Zürich';
...
请注意,我使用:encoding(UTF-8)
代替:utf8
。后者是不正确的,即使在这个例子中两者看起来都是等价的。
答案 1 :(得分:0)
Perl中的字符串可以存储为字节字符串或Unicode字符串。在您的情况下,您正在定义Byte Strings。
问题:您的程序源保存在哪种编码中?
您对$line_text
的第一个作业是程序源编码中的字节字符串。使用:raw
将此字节字符串打印到文件时,它将完全按照存储在源中的方式进行转储。如果使用编码器打印编码的字节串,如:utf8
,则会得到一个双重编码的字符串,这不太可能是一个好主意。如果您的程序以UTF8保存,那么您可以use utf8;
将该字符串文字解码为字符串。当您使用:utf8
打印正确解码的字符串时,它会将字符正确编码为UTF8。
故事的道德:虽然传递原始字节在某些情况下可以正常工作,但解码输入(和字符串文字)并对输出进行编码通常更好。