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版本更长,但运行时一致性更高检查并且更容易增强.因人而异. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |