+ -
当前位置:首页 → 问答吧 → 谈谈 Perl 的文件句柄和 typeglob 的关系

谈谈 Perl 的文件句柄和 typeglob 的关系

时间:2010-12-31

来源:互联网

本帖最后由 黑色阳光_cu 于 2010-12-31 12:18 编辑

Perl 的文件句柄本质上是保存在 typeglob 里的,当你调用 open 时,有一些奇妙的事发生了:
  1. open(FH, "<", "urfile.txt");
  2. warn *FH{IO};
复制代码
可以看到,FH 的文件句柄保存在 *FH 里,具体的是保存在 *FH{IO} 里。FH 是一个裸词,在 open 调用里,Perl 会把裸词转为对应的 typeglob,相当于
  1. open(*FH, "<", "urfile.txt");
复制代码
所以,当要传递句柄时,要把裸词形式的句柄转成对应的 typeglob 或者 typeglob 的引用:
  1. sub func
  2. {
  3.         my $fp = $_[0];
  4.         while (<$fp>)
  5.         {
  6.                 print;
  7.         }
  8. }

  9. open(FH, "<", "urfile.txt");
  10. func(\*FH);
复制代码
这样子相当不方便,后来,Perl 允许这样子的语法:
  1. open(my $fp, "<", "urfile.txt");
  2. warn $fp;
  3. while (<$fp>)
  4. {
  5.         print;
  6. }
复制代码
可以看到 $fp 就是一个 typeglob 的引用。打印 *{$fp} 时显示 *main::$fp , 但下面这个代码表明,直接用当前的 *main::$fp 却不行:
  1. open(my $fp, "<", "urfile.txt");
  2. warn *{$fp};
  3. while (<*{'main::$fp'}>)
  4. {
  5.         print;
  6. }
复制代码
再则,当 $fp 超过作用域时,文件会自动被关闭, $fp 这个句柄是词法作用域的。 看来 $fp 不简单的等同于 \*{'main::$fp'} ,那又是怎么做到的?

因为,typeglob 是一个全局的资源,为了取得词法域的效果,可以借助于 local 。open($fp, "<", "urfile.txt") 大概等同于这个写法:
  1. my $fp;
  2. {
  3.         local *{'main::$fp'};
  4.         open(*{'main::$fp'}, "<", "urfile.txt");
  5.         my $tmp = *{'main::$fp'};
  6.         $fp = \$tmp;
  7. }

  8. warn $fp;
  9. while (<$fp>)
  10. {
  11.         print;
  12. }
复制代码
注意那个 $tmp ,当 my $tmp = *{'main::$fp'} 后,$tmp 和 *{'main::$fp'} 指向同一个 typeglob 值。当超过作用域后,*{'main::$fp'} 恢复原值,则 $fp 是 $tmp 的唯一引用。所以,超过作用域后,$fp 就不简单的等同于当前的 \*{'main::$fp'} ,而当 唯一引用 $fp 也超过作用域时,文件就被自动关闭了。借助于 local ,Perl 提供了词法作用域的文件句柄。在这里,也可以看出 Perl 解决问题的智慧。

作者: 黑色阳光_cu   发布时间: 2010-12-31

你知道的太多了

作者: yiten   发布时间: 2010-12-31

写的真不错,深刻

作者: jovelva   发布时间: 2010-12-31

没研究过没有发言权,我只知道我相当的不看不顺眼这种打开文件的方式

最顺眼,最省事的是这种,算上空格少敲4个键,曾经还看到过一道题,问这两种方式有啥不同!出这题的人脑残!!!

open(FH, "<urfile.txt");

作者: meihuaqi   发布时间: 2010-12-31