1

IO :: File-> open()は、次のプログラムでのopen()の使用を尊重していないようです。これは私には奇妙で、ドキュメントに反しているようです。または多分私はそれを間違っています。IO::Fileを使用しないようにコードを書き直すのは難しいことではありません。

出力は次のようになると思います

$VAR1 = \"Hello \x{213} (r-caret)";

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

しかし、このエラーが発生します:「おっと:./run.plの33行目に印刷中の不正な形式のUTF-8文字(文字列の予期しない終わり)」。

それは私にはまったく正しくないようです。

#!/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: $_";
};
4

2 に答える 2

7

ここで起こっているのuse open字句プラグマopen()であり、同じ字句スコープ内の呼び出しにのみ影響することを意味すると思います。字句スコープは、コードが同じブロックにある場合です。 IO::File->openはラッパーであるため、字句スコープの外open()で呼び出しています。open()

{
    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...
}

上記の例では、の字句スコープfoo()内で呼び出されていますが、内部のコードは外部にあるため、その影響を受けません。use openfoo()

IO::Fileがopen.pmを継承した場合は礼儀正しくなります。これは簡単ではありませんが、可能です。同様の問題がautodieを悩ませました。 これは修正され、修正はおそらくIO::Fileで機能する可能性があります。

于 2013-01-30T02:28:08.830 に答える
3

[これは答えではありませんが、コメントに収まらないバグの通知です。]

ファイルにはバイトのみを含めることができます。$strバイトではない値が含まれています。したがって、

open(my $fh, '<', \$str)

意味がありません。そのはず

open(my $fh, '<', \encode_utf8($str))

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',
      );
   }
}

出力:

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}"
于 2013-01-30T02:29:50.647 に答える