文件和文件句柄

Scalar变量除了能够包含数值、字符串、引用或者undef,还能包含一个文件句柄。文件句柄本质上就是对于某个文件中某个位置的引用。

[open](http://perldoc.perl.org/functions/open.html)可以把一个scalar变量编程文件句柄。我们必须给open提供一个打开模式。模式<表示我们想要读取这个文件:

  1. my $f = "text.txt";
  2. my $result = open my $fh, "<", $f;
  3. if(!$result) {
  4. die "Couldn't open '".$f."' for reading because: ".$!;
  5. }

如果成功,open返回true,否则返回false,并且错误消息会被填入内置变量$!。就像你在上面的代码里看到的,你总是应该检查open操作是否成功完成了,不过像那样检查真是冗长乏味,更常见的写法是:

  1. open(my $fh, "<", $f) || die "Couldn't open '".$f."' for reading because: ".$!;

注意,你需要在open的参数列表两边加上括号。

要从文件句柄中读取一行,可以用内置函数[readline](http://perldoc.perl.org/functions/readline.html)readline返回一整行文本,并且结尾有一个换行符(除了文件末尾的那行可能例外),如果已经读到文件末尾则返回undef

  1. while(1) {
  2. my $line = readline $fh;
  3. last unless defined $line;
  4. # 处理$line...
  5. }

可以用[chomp](http://perldoc.perl.org/functions/chomp.html)移除末尾可能存在的换行符:

  1. chomp $line;

请注意,chomp直接作用于$line上,因此$line = chomp $line可能不会得到你想要的东西。

你也可以用[eof](http://perldoc.perl.org/functions/eof.html)来检测是否已经读到文件末尾:

  1. while(!eof $fh) {
  2. my $line = readline $fh;
  3. # 处理$line...
  4. }

不过使用while(my $line = readline $fh)的时候要小心了,因为如果$line的内容恰好是"0",循环可能过早结束。如果你想要这样写,Perl提供了<>功能上更安全的运算符,你可以用它包围readline。这种写法很常见而且也非常安全:

  1. while(my $line = <$fh>) {
  2. # 处理$line...
  3. }

甚至:

  1. while(<$fh>) {
  2. # 处理$_...
  3. }

如果要写一个文件,首先你需要另一种打开模式。模式>表示我们想要写入这个文件。(如果目标文件存在的话,>会清空它,如果你只是想附加在文件的原有内容后面,你应该用模式>>。)然后,将文件句柄作为print方法的第0个参数提供就行了。

  1. open(my $fh2, ">", $f) || die "Couldn't open '".$f."' for writing because: ".$!;
  2. print $fh2 "The eagles have left the nest";

请注意在$fh2和后面的参数之间没有逗号。

文件句柄在超出它们的作用域以后会自动关闭,如果你想主动关闭:

  1. close $fh2;
  2. close $fh;

有三个文件句柄以全局常量形式存在:STDINSTDOUTSTDERR,它们在脚本开始时就被自动打开。要读取一行用户的输入:

  1. my $line = <STDIN>;

如果只是等待用户按回车:

  1. <STDIN>;

调用<>而不提供文件句柄参数,表示从STDIN或者在Perl脚本启动时指定的参数指向的文件中读取。

你可能已经知道了,如果不提供文件句柄,print默认会打印到STDOUT

文件检测

内置函数-e用于测试文件是否存在。

  1. print "what" unless -e "/usr/bin/perl";

内置函数-d用于测试文件是否是目录。

内置函数-f用于测试文件是否是普通文件。

这只是一大波形如-X的函数中的三个,其中X是某些小写或大写字母。这类函数被称作文件检测函数。请注意字母前面的减号,用Google搜索的时候,减号表示从搜索结果中排除包含这个词的结果,这样就导致很难用Google搜索文件检测函数了!用“Perl file test”来搜索就好。