perl – 如何将文件句柄传递给函数?
|
当我运行下面的代码时,我得到了
Can't use string ("F") as a symbol ref while "strict refs" in use at ./T.pl line 21.
第21行是 flock($fh,LOCK_EX); 我究竟做错了什么? #!/usr/bin/perl
use strict;
use warnings;
use Fcntl ':flock','SEEK_SET'; # file locking
use Data::Dumper;
# use xx;
my $file = "T.yaml";
my $fh = "F";
my $obj = open_yaml_with_lock($file,$fh);
$obj->{a} = 1;
write_yaml_with_lock($obj,$fh);
sub open_yaml_with_lock {
my ($file,$fh) = @_;
open $fh,'+<',$file;
flock($fh,LOCK_EX);
my $obj = YAML::Syck::LoadFile($fh);
return $obj;
}
sub write_yaml_with_lock {
my ($obj,$fh) = @_;
my $yaml = YAML::Syck::Dump($obj);
$YAML::Syck::ImplicitUnicode = 1;
seek $fh,SEEK_SET; # seek back to the beginning of file
print $fh $yaml . "---n";
close $fh;
}
解决方法
你做错了是使用字符串“F”作为文件句柄.这个
从来没有像这样的东西;你可以用一个裸字作为 filehandle(打开FH,……;打印FH …),或者你可以传入 空标量和perl会为其分配一个新的打开文件对象 变量.但是如果你传入字符串F,那么你需要参考 然后处理为F,而不是$fh.但是,不要这样做. 改为: sub open_yaml_with_lock {
my ($file) = @_;
open my $fh,$file or die $!;
flock($fh,LOCK_EX) or die $!;
my $obj = YAML::Syck::LoadFile($fh); # this dies on failure
return ($obj,$fh);
}
我们在这里做了几件事.一,我们不存储 sub open_yaml_with_lock {
open $_[0],$_[1] or die $!;
...
}
open_yaml_with_lock(my $fh,'filename');
write_yaml_with_lock($fh);
但实际上,这是一团糟.把这些东西放在一个物体里.造新 我们在这里做的另一件事是检查错误.是的,磁盘可以 如果您使用autodie qw / open flock编写脚本将是正确的 无论如何,总结一下: >定义$fh时不要打开$fh.写下我的$fh给 更新 好的,这是如何使这更多的OO.首先,我们将做“纯Perl”OO package LockedYAML;
use strict;
use warnings;
use Fcntl ':flock','SEEK_SET';
use YAML::Syck;
use autodie qw/open flock sysseek syswrite/;
sub new {
my ($class,$filename) = @_;
open my $fh,$filename;
flock $fh,LOCK_EX;
my $self = { obj => YAML::Syck::LoadFile($fh),fh => $fh };
bless $self,$class;
return $self;
}
sub object { $_[0]->{obj} }
sub write {
my ($self,$obj) = @_;
my $yaml = YAML::Syck::Dump($obj);
local $YAML::Syck::ImplicitUnicode = 1; # ensure that this is
# set for us only
my $fh = $self->{fh};
# use system seek/write to ensure this really does what we
# mean. optional.
sysseek $fh,SEEK_SET;
syswrite $fh,$yaml;
$self->{obj} = $obj; # to keep things consistent
}
然后,我们可以在主程序中使用该类: use LockedYAML;
my $resource = LockedYAML->new('filename');
print "Our object looks like: ". Dumper($resource->object);
$resource->write({ new => 'stuff' });
错误将抛出异常,可以使用 最后,穆斯版本: package LockedYAML;
use Moose;
use autodie qw/flock sysseek syswrite/;
use MooseX::Types::Path::Class qw(File);
has 'file' => (
is => 'ro',isa => File,handles => ['open'],required => 1,coerce => 1,);
has 'fh' => (
is => 'ro',isa => 'GlobRef',lazy_build => 1,);
has 'obj' => (
is => 'rw',isa => 'HashRef',# or ArrayRef or ArrayRef|HashRef,or whatever
lazy_build => 1,trigger => sub { shift->_update_obj(@_) },);
sub _build_fh {
my $self = shift;
my $fh = $self->open('rw');
flock $fh,LOCK_EX;
return $fh;
}
sub _build_obj {
my $self = shift;
return YAML::Syck::LoadFile($self->fh);
}
sub _update_obj {
my ($self,$new,$old) = @_;
return unless $old; # only run if we are replacing something
my $yaml = YAML::Syck::Dump($new);
local $YAML::Syck::ImplicitUnicode = 1;
my $fh = $self->fh;
sysseek $fh,$yaml;
return;
}
这类似地使用: use LockedYAML;
my $resource = LockedYAML->new( file => 'filename' );
$resource->obj; # the object
$resource->obj( { new => 'object' }); # automatically saved to disk
Moose版本更长,但运行时一致性更高检查并且更容易增强.因人而异. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
