open - perl 编译指示用于设置输入和输出的默认 PerlIO 层
use open IN => ':crlf', OUT => ':raw';
open my $in, '<', 'foo.txt' or die "open failed: $!";
my $line = <$in>; # CRLF translated
close $in;
open my $out, '>', 'bar.txt' or die "open failed: $!";
print $out $line; # no translation of bytes
close $out;
use open OUT => ':encoding(UTF-8)';
use open IN => ':encoding(iso-8859-7)';
use open IO => ':locale';
# IO implicit only for :utf8, :encoding, :locale
use open ':encoding(UTF-8)';
use open ':encoding(iso-8859-7)';
use open ':locale';
# with :std, also affect global standard handles
use open ':std', ':encoding(UTF-8)';
use open ':std', OUT => ':encoding(cp1252)';
use open ':std', IO => ':raw :encoding(UTF-16LE)';
只要 Perl 配置为使用 PerlIO 作为其 IO 系统(自 5.8 版本以来一直是默认设置,并且自 5.16 版本以来是唯一支持的配置),现在已实现对 I/O 层的全面支持。
open
编译指示用作声明所有 I/O 的默认“层”(以前称为“规则”)的接口之一。在该编译指示的词法范围内找到的任何 open()、readpipe()(也称为 qx//)和类似运算符都将通过 ${^OPEN}
变量使用声明的默认值。
层通常以冒号开头指定。您可以将多个层作为以空格分隔的字符串指定。有关可用层的更多信息,请参见 PerlIO。
使用 IN
子编译指示,您可以声明输入流的默认层,使用 OUT
子编译指示,您可以声明输出流的默认层。使用 IO
子编译指示(对于 :utf8
、:locale
或 :encoding
可以省略),您可以同时控制输入和输出流。
当 open() 给定一个显式的层列表(使用三参数语法)时,它们会覆盖使用该编译指示声明的列表。open() 也可以给定一个冒号 (:) 作为层名称,以覆盖该编译指示并使用 "PerlIO 中的默认值以及如何覆盖它们" 中详细说明的默认值。
要从任意文本编码转换到任意文本编码,请使用 :encoding
层。:encoding
中的编码名称匹配很宽松:不区分大小写,并且许多编码都有多个别名。有关详细信息和支持的语言环境列表,请参见 Encode::Supported。
如果您想根据您的语言环境环境变量设置您的编码层,您可以使用 :locale
伪层。例如
$ENV{LANG} = 'ru_RU.KOI8-R';
# the :locale will probe the locale environment variables like LANG
use open OUT => ':locale';
open(my $out, '>', 'koi8') or die "open failed: $!";
print $out chr(0x430); # CYRILLIC SMALL LETTER A = KOI8-R 0xc1
close $out;
open(my $in, '<', 'koi8') or die "open failed: $!";
printf "%#x\n", ord(<$in>); # this should print 0xc1
close $in;
:locale
的逻辑在 "encoding 中的 :locale
子pragma" 中有完整描述,但简而言之,它首先尝试使用 nl_langinfo(CODESET),然后从 LC_ALL 和 LANG 环境变量中猜测。:locale
还隐式地开启 :std
。
:std
不是一个层,而是一个额外的子pragma。当在导入列表中指定时,它会激活一个额外的功能,将为输入/输出句柄选择的层推送到标准文件句柄(STDIN、STDOUT、STDERR)。如果新的层和现有的层堆栈都以 :encoding
层结尾,则现有的 :encoding
层也将被移除。
例如,如果输入和输出都被选择为 :encoding(UTF-8)
,那么 :std
将意味着 STDIN、STDOUT 和 STDERR 也将设置 :encoding(UTF-8)
。另一方面,如果只选择输出为 :encoding(koi8r)
,那么 :std
将导致只有 STDOUT 和 STDERR 为 koi8r
。
:std
的效果不是词法上的,因为它修改了全局句柄的层堆栈。如果您希望只应用此全局效果,而不应用对在该作用域中打开的句柄的效果,则可以在其自己的词法作用域中隔离对该 pragma 的调用。
{ use open ':std', IO => ':encoding(UTF-8)' }
在 Perl 5.34 之前,:std
仅应用第一个提供的层,该层要么是 :utf8
,要么具有层参数,例如 :encoding(UTF-8)
。从 Perl 5.34 开始,它将应用与提供给 ${^OPEN}
的相同的层堆栈。
PerlIO::Layer
中有一个类方法 find
,它被实现为 XS 代码。它由 import
调用以验证层。
PerlIO::Layer::->find("perlio")
返回值(如果已定义)是一个 Perl 对象,属于 PerlIO::Layer
类,该类由 perlio.c 中的 C 代码创建。目前,您在 perl 级别上无法对该对象做任何有用的操作。
"perlfunc 中的 binmode","perlfunc 中的 open",perlunicode,PerlIO,encoding