FileHandle に書き込んでいたデータの出力先を変数にしてくれるIO::Scalar
タイトルの通り今回したかったのはファイルハンドルを使って
ファイルへ出力していたコードの出力先を変数にしたかった。
そういうことをしてくれる小粋なモジュール IO::Scalar を使って対応しました。
これがまた便利で、数行書き換えるだけでよくてパフォーマンスは使う前と後で、それほど差異はありませんでした。
通常の FileHandle を使ったコード
#!/usr/bin/perl use strict; use warnings; open my $fh, '>', 'file' or die $! print $fh 'hoge'; #この時点で file とう名前のファイルがカレントディレクトリにつくられます。 1;
IO::Scalar を使って出力先を変数にしたコード
#!/usr/bin/perl
use strict;
use warnings;
use IO::Scalar;
my $file;
my $out;
{
my $fh = IO::Scalar->new(\$out);
local *F = $fh;
$file = *F;
print $file "hoge\n";
}
warn $out;
1;
で、調べていくと IO::String というモジュールも同じようなことをしてくれることを知った。
ちょっと試してみたけどインターフェースはさほどかわりない感じ。
というわけでベンチ。
Rate IO_STRING IO_SCALAR IO_STRING 210/s -- -44% IO_SCALAR 373/s 77% --
見た通り IO::Scalar の方がはやいですね。
試したコードはこれ。
#!/usr/bin/perl
use strict;
use warnings;
use IO::String;
use IO::Scalar;
use Benchmark qw/cmpthese/;
my @data = map { int rand 1000 } 1..1000;
cmpthese(10000, {
IO_STRING => \&with_io_string,
IO_SCALAR => \&with_io_scalar,
});
sub with_io_scalar {
my $output;
my $ios = IO::Scalar->new(\$output);
local *STDOUT = $ios;
print $_ for @data;
# warn $output;
}
sub with_io_string {
my $output;
my $ios = IO::String->new(\$output);
local *STDOUT = $ios;
print $_ for @data;
# warn $output;
}
1;