【问题标题】:Why does PerlIO::encoding insert an additional utf8 layer?为什么 PerlIO::encoding 会插入一个额外的 utf8 层?
【发布时间】:2015-07-09 19:27:42
【问题描述】:

documentation for PerlIO 说:

:encoding 在 open() 或 binmode() 中使用 :encoding(ENCODING) 来 安装一个透明地执行字符集和编码的层 转换,例如从 Shift-JIS 到 Unicode。注意 在 stdio 下, :encoding 也启用 :utf8 。请参阅 PerlIO::encoding 更多信息。

这是一个测试脚本:

use feature qw(say);
use strict;
use warnings;

my $fn = 'test.txt';
for my $mode ('>', '>:encoding(utf8)' ) {
    open( my $fh, $mode, $fn);
    say  join ' ', (PerlIO::get_layers($fh));
    close $fh;
}

输出是:

unix perlio
unix perlio encoding(utf8) utf8

为什么我会在这里获得额外的utf8 层?

【问题讨论】:

    标签: perl encoding


    【解决方案1】:

    出于需要 Perl 内部知识的原因。


    当您将数字4 存储为标量时,它可以存储为有符号整数、无符号整数或浮点数。你不知道哪个被使用,你没有任何理由关心哪个被使用。 Perl 会根据需要自动转换。

    字符串也是同样的情况。它们有两种存储格式。你的名字就是最好的例子。 “Håkon Hægland”可以存储为

    48.E5.6B.6F.6E.20.48.E6.67.6C.61.6E.64
    

    或作为

    48.C3.A5.6B.6F.6E.20.48.C3.A6.67.6C.61.6E.64
    

    名为UTF8 的标志表示存储格式的选择。这对用户是透明的(或者至少应该是透明的)。

    $ perl -Mutf8 -E'
        $_ = "Håkon Hægland";
        utf8::downgrade( $d = $_ );  # Converts to the first format mentioned above.
        utf8::upgrade(   $u = $_ );  # Converts to the second format mentioned above.
        say $d eq $u ? "eq" : "ne";
    '
    eq
    

    虽然它对您是透明的,但它对 Perl 本身却远非透明。每当您操作字符串时,Perl 都必须检查它以哪种存储格式存储。例如,如果你连接两个字符串,Perl 必须在执行连接之前确保它们使用相同的存储格式,并在必要时转换一个。

    它对 PerlIO 也不透明。 PerlIO 与 Perl 的其余部分一样,必须处理字符串缓冲区中的字节,而不是您在 Perl 级别看到的内容。有时,这些字节注定是清除了UTF8 标志的标量的字符串缓冲区,有时,这些字节注定是设置了UTF8 标志的标量的字符串缓冲区。 PerlIO 需要跟踪它。当通过从句柄读取获得的标量需要设置UTF8 标志时,PerlIO 不会在层与层之间携带标志,而是添加:utf8 层。


    所以,:encoding 转换了形成的字节

    Håkon Hægland
    

    从指定编码到

    48.C3.A5.6B.6F.6E.20.48.C3.A6.67.6C.61.6E.64
    

    :utf8 会导致标量设置UTF8 标志,从而导致生成的标量包含

    U+0048.00E5.006B.006F.006E.0020.0048.00E6.0067.006C.0061.006E.0064
    

    【讨论】:

    猜你喜欢
    • 2014-02-23
    • 1970-01-01
    • 1970-01-01
    • 2014-03-26
    • 2014-12-20
    • 1970-01-01
    • 1970-01-01
    • 2012-09-25
    • 1970-01-01
    相关资源
    最近更新 更多