首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Perl的IO::File并使用open qw(:utf8)

Perl的IO::File并使用open qw(:utf8)
EN

Stack Overflow用户
提问于 2013-01-30 10:20:15
回答 2查看 2.8K关注 0票数 1

在下面的程序中,IO::File->open()似乎不尊重使用open(),这对我来说很奇怪,而且似乎与文档不符。也许我做错了。重写我的代码不使用IO::File应该不难。

我希望输出结果是

代码语言:javascript
复制
$VAR1 = \"Hello \x{213} (r-caret)";

Hello ȓ (r-caret)
Hello ȓ (r-caret)
Hello ȓ (r-caret)

但是我得到了这个错误:"Oops:错误的UTF-8字符(意外的字符串结尾) in print at ./run.pl行33。“

这对我来说一点都不对劲。

代码语言:javascript
复制
#!/usr/local/bin/perl

use utf8;
use v5.16;
use strict;
use warnings;
use warnings qw(FATAL utf8);
use diagnostics;
use open qw(:std :utf8);
use charnames qw(:full :short);

use File::Basename;
my $application = basename $0;

use Data::Dumper;
$Data::Dumper::Indent = 1;

use Try::Tiny;

my $str = "Hello ȓ (r-caret)";

say Dumper(\$str);

open(my $fh, '<', \$str);
print while ($_ = $fh->getc());
close($fh);
print "\n";

try {
  use IO::File;
  my $fh = IO::File->new();
  $fh->open(\$str, '<');
  print while ($_ = $fh->getc());
  $fh->close();
  print "\n";
}
catch {
  say "\nOops: $_";
};

try {
  use IO::File;
  my $fh = IO::File->new();
  $fh->open(\$str, '<:encoding(UTF-8)');
  print while ($_ = $fh->getc());
  $fh->close();
  print "\n";
}
catch {
  say "\nOops: $_";
};
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-01-30 10:28:09

我相信这里发生的事情是use open是一个词法编译指示,这意味着它只影响在相同词法范围内对open()的调用。词法作用域是指代码在同一块中。IO::File->openopen()的包装器,因此在其词法范围之外调用open()也是如此。

代码语言:javascript
复制
{
    use open;

    ...same lexical scope...

    {
        ...inner lexical scope...
        ...inherits from the outer...
    }

    ...still the same lexical scope...
    foo();
}

sub foo {
    ...outside "use open"'s lexical scope...
}

在上面的示例中,即使在use open的词法范围内调用foo(),但foo()内的代码在其作用域外,因此不受其影响。

如果IO::File继承了open.pm,这将是一种礼貌。这不是微不足道的,但却是可能的。类似的问题也困扰着autodieIt was fixed和修复可能会在IO::File中起作用。

票数 7
EN

Stack Overflow用户

发布于 2013-01-30 10:29:51

这不是一个答案,而是一个错误的通知,不适合在评论中。

文件只能包含字节。$str包含的值不是字节。因此,

代码语言:javascript
复制
open(my $fh, '<', \$str)

这没有任何意义。它应该是

代码语言:javascript
复制
open(my $fh, '<', \encode_utf8($str))

代码语言:javascript
复制
use utf8;
use v5.16;
use strict;
use warnings;
use warnings qw(FATAL utf8);
use open qw( :std :utf8 );
use Encode qw( encode_utf8 );
use Data::Dumper qw( Dumper );

sub dump_str {
   local $Data::Dumper::Useqq = 1;
   local $Data::Dumper::Terse = 1;
   local $Data::Dumper::Indent = 0;
   return Dumper($_[0]);
}

for my $encode (0..1) {
   for my $orig ("\x{213}", "\x{C9}", substr("\x{C9}\x{213}", 0, 1)) {
      my $file_ref = $encode ? \encode_utf8($orig) : \$orig;
      my $got = eval { open(my $fh, '<', $file_ref); <$fh> };
      printf("%-10s  %-6s  %-9s => %-10s => %s\n",
         $encode ? "bytes" : "codepoints",
         defined($got) && $orig eq $got ? "ok" : "not ok",
         dump_str($orig),
         dump_str($$file_ref),
         defined($got) ? dump_str($got) : 'DIED',
      );
   }
}

输出:

代码语言:javascript
复制
codepoints  ok      "\x{213}" => "\x{213}"  => "\x{213}"
codepoints  not ok  "\311"    => "\311"     => DIED
codepoints  not ok  "\x{c9}"  => "\x{c9}"   => DIED
bytes       ok      "\x{213}" => "\310\223" => "\x{213}"
bytes       ok      "\311"    => "\303\211" => "\x{c9}"
bytes       ok      "\x{c9}"  => "\303\211" => "\x{c9}"
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14595624

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档