【问题标题】:How Can I Store a File Handle in a Perl Object and how can I access the result?如何在 Perl 对象中存储文件句柄以及如何访问结果?
【发布时间】:2012-12-30 08:36:39
【问题描述】:

我想在 Perl 对象中存储一个文件句柄。这是我的做法。

sub openFiles {
     my $self = shift;
     open (my $itemsFile, "<", "items.txt")     or die $!;
     open (my $nameFile,  "<", "FullNames.txt") or die $!;      
     $self->{itemsFile} = $itemsFile;                   
     $self->{nameFile}  = $nameFile;
     return $self;
}

然后我希望从这些文件之一中访问一些信息。这是我的做法。

sub getItemDescription {
     my $self = @_;
     chomp(my $record = $self->{itemsFile});
     return $record;
}

我尝试在另一个过程中访问它,如下所示:

print "Test 3: $self->getItemDescription()\n";

我的问题如下:

  1. 我在对象中保存文件句柄的方式是否正确?如果不是,怎么错了?
  2. 我读取文件行的​​方式是否正确?如果没有,我怎样才能正确?
  3. 最后,我打印返回对象的方式是否正确?

这对我来说真的很重要。如果有任何方法可以改进我的代码结构,即为文件处理创建一个全局变量或更改对象的结构,请告诉我。

【问题讨论】:

    标签: perl object file-io methods perl-data-structures


    【解决方案1】:

    openFiles 是正确的。

    错误主要发生在getItemDescription方法。

    如前所述,首先my $self = @_; 应该是my ($self) = @_;

    但是,问题的症结是通过以下方式解决的:

    chomp(my $record = $self-&gt;{itemsFile});改为两行:

    $file1 = $self-&gt;{itemsFile};

    chomp(my $record = $file1);

    为了澄清,您必须(根据我的经验并尝试了所有建议的解决方案)使用标量值。

    最后,请参阅 ikagami 答案的最后两段。

    【讨论】:

      【解决方案2】:

      我在对象中保存文件句柄的方式是否正确?

      是的。

      我读取文件行的​​方式正确吗?

      没有。那只是分配文件句柄。使用readline 运算符从文件中读取一行。

      通常会使用readline 运算符的&lt;...&gt; 语法,但&lt;...&gt;readline(...)glob(qq&lt;...&gt;) 的快捷方式,Perl 认为&lt;$self-&gt;{itemsFile}&gt;glob(qq&lt;$self-&gt;{itemsFile}&gt;) 的缩写。您必须专门使用readline

      my $record = readline($self->{itemsFile});
      chomp($record) if defined($record);
      

      或者做一些额外的工作

      my $fh = $self->{itemsFile};
      my $record = <$fh>;
      chomp($record) if defined($record);
      

      (请注意,我不会无条件调用chomp,因为readline/&lt;&gt; 可以返回undef。)

      最后,我打印返回对象的方式是否正确?

      我猜你的意思是返回的字符串,就像getItemDescription 返回的字符串一样。问题是,您从未真正调用过该方法。 -&gt;getItemDescription() 在双引号字符串文字中没有任何意义,即使在变量之后也是如此。您需要将$self-&gt;getItemDescription() 移出双引号。

      您也未能检查是否已到达文件末尾。

      【讨论】:

      • 它不工作。我得到的响应是 'TSJobsGenerator=HASH(0x2592d4)->getItemDescription(), Can't use string ("1") as HASH ref while "strict refs" in use at TSJobsGenerator.pm line 62.
      • 那是因为my $self = @_; 中的不相关错误。应该是my ($self) = @_;
      【解决方案3】:

      你很接近。

      要从文件句柄中读取记录(行),请在将文件句柄分配给“简单标量”后使用内置的readline 函数或&lt;...&gt; 运算符(请参阅下面的编辑)。

      chomp(my $record = readline( $self->{itemsFile} );
      
      my $fh = $self->{itemsFile};
      chomp(my $record = <$fh>);
      

      您的getItemDescription 方法中还有一个错误。你会想说

      my ($self) = @_;
      

      而不是

      my $self = @_;
      

      后面的调用是一个数组的标量赋值,解析为数组的长度,而不是数组的第一个元素。

      编辑:&lt;$self-&gt;{itemsFile}&gt;&lt;{$self-&gt;{itemsFile}}&gt; 不起作用,as perlop explains

      如果尖括号中的内容既不是文件句柄,也不是包含文件句柄名称、typeglob 或 typeglob 引用的简单标量变量,则将其解释为要通配的文件名模式,以及文件名列表或下一个文件名根据上下文返回列表中的。这种区别仅由句法基础决定。这意味着&lt;$x&gt; 始终是来自间接句柄的readline(),但&lt;$hash{key}&gt; 始终是glob()。那是因为$x 是一个简单的标量变量,但$hash{key} 不是——它是一个哈希元素。即使&lt;$x &gt;(注意多余的空格)也被视为glob("$x "),而不是readline($x)

      【讨论】:

      • 酷。那么你会建议一个全局变量 $fileHandle 我用于整个对象的文件吗?从架构的角度来看,这是最好的解决方案吗?
      • 什么?不,没有人建议使用全局变量。那将是一个糟糕的主意。
      • Ikegami,如果我的理解是正确的,暴民是说根据他的编辑,将文件句柄存储在对象中不会被正确读取,还是我遗漏了什么?
      • 什么的。他也没有这么说。你比他更明白我的回答吗?我们都在说同样的话。
      • 不能正常工作的是文件句柄的“复杂表达式”和&lt;&gt; 运算符的组合。您可以将复杂的标量传递给readline。或者您可以将对象成员复制到一个简单的标量并使用&lt;&gt; 运算符。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-07
      相关资源
      最近更新 更多