这是定位警告触发位置的另一种方法,使用无缓冲sysread
use warnings;
use strict;
binmode STDOUT, ':utf8';
binmode STDERR, ':utf8';
my $file = 'test.txt';
open my $fh, "<:encoding(UTF-8)", $file or die "Can't open $file: $!";
$SIG{__WARN__} = sub { print "\t==> WARN: @_" };
my $char_cnt = 0;
my $char;
while (sysread($fh, $char, 1)) {
++$char_cnt;
print "$char ($char_cnt)\n";
}
文件test.txt
是由发布的程序编写的,只是我必须添加它才能重现该行为 - 它在 v5.10 和 v5.16 上运行时没有警告。我添加了\x{234234}
到最后。可以通过以下方式跟踪行号$char =~ /\n/
.
The sysread
回报undef
出错时。它可以被移动到身体里while (1)
允许读取继续并捕获所有警告,突破0
(在 EOF 时返回)。
这打印
H (1)
e (2)
l (3)
l (4)
o (5)
(6)
A (7)
å (8)
a (9)
==> WARN: Code point 0x234234 is not Unicode, may not be portable at ...
(10)
虽然这确实捕获了警告的字符,但使用以下命令重新读取文件Encode
可能比伸手去拿更好sysread
,特别是如果sysread
uses Encode
.
然而,Perl 是utf8
在内部,我不确定sysread
needs Encode
.
笔记。该页面为sysread http://perldoc.perl.org/functions/sysread.html支持其在具有编码层的数据上的使用
请注意,如果文件句柄已标记为:utf8
统一码
读取的是字符而不是字节(LENGTH、OFFSET 和
返回值sysread
是 Unicode 字符)。这:encoding(...)
层隐含地引入了:utf8
层。
看binmode
, open
,以及open
pragma.
Note显然,在某个版本之后事情已经发生了变化sysread
不支持编码层。上面的链接对于旧版本(其中一个是 v5.10)确实显示了引用的内容,而新版本则告诉我们会有例外。