Perl语言入门:文件操作和异常处理初步

Perl使用一种叫“文件句柄”的变量来操作文件

在文章末尾将补充讲解Perl5新加入的语法特性


文件句柄

文件句柄(filehandle)是文件操作中用来存放文件唯一标识符的名称空间

或者说,文件句柄是一个I/O连接的名称

在文件I/O中,要从一个文件读取数据,应用程序要调用操作系统函数并传入文件名,然后选取一个到该文件的路径来打开文件;用来沟通文件和I/O原始数据的就是文件句柄

Perl内置六种保留文件句柄 STDIN STDOUT STDERR DATA ARGV ARGVOUT
对应,标准输入、标准输出、标准错误、从执行它的脚本获取输入、命令行参数、命令行参数输出

文件句柄是文件操作的基础,可以作为参数传给「打开文件函数」

文件句柄通常大写


open函数

open CONFIG, '读file.txt';

其中,“CONFIG”就是程序员指定的文件句柄,该句打开文件句柄OCNFIG,并从file.txt中读入数据(默认情况下就是“读”,所以 ‘<’符号是可省略的)

几种open函数的形式:

open HANDLE1, '; #读入数据
open HANDLE2, '>b.txt'; #写入数据
open HANDLE3, '>>c.txt';    #追加数据

关闭文件(句柄)

所谓“关闭文件句柄”,就是改告诉操作系统“程序对文件的数据流操作已经完成,请系统将尚未写入的输出数据写入磁盘以免有人等着使用”

假设你熟悉I/O系统,应该知道这里还有一些细节:一般来说,当文件句柄关闭时,如果文件中仍有输入它会被忽略;如果管道中仍有输入,那么对这个管道进行读写操作的程序会收到管道被关闭的信号;如果有文件或管道的输出,那么缓冲区会被刷新(也就是保存在缓冲区的内容会马上发送出去);如果文件句柄加了锁,那么该锁会被释放……

当重新打开文件句柄时,Perl会自动关闭原先的文件句柄。在程序结束时Perl也会自动关闭所有的文件句柄

正因为Perl是这样贴心,以至于我们根本不需要操作文件句柄的关闭问题;但是如果要代码写的好看些,最好在适当的时候加上close函数


die函数

Perl使用die函数来捕获异常

可以通过操作的状态返回码来避免异常:

my $success = open LOG, '>>', 'logfile';
if(! $success){
    #open操作失败
    ...
}

现在可以使用die函数来捕获异常(规范写法):

if(! open LOG, '>>', 'logfile'){
    die "Cannot create logfile: $!";
} 

如果open失败,die会终止程序的运行,并且告诉我们无法创建日志文件
冒号后面的$!代表(保存着)“可读的系统错误信息”,如permission deniedfile not found之类的语句
另外die函数还会打印出出现问题的程序所在行数

Cannot create logfile: permission denied at your_program line 1234

如果不想输出行数信息,可以在die函数的末尾加上\n换行符

if(@ARGV<2){
    die "Not enough arguments\n";
}

warn函数

warm函数的功能和die函数的功能差不多

不同的是,warm函数不会终止程序的运行


使用文件句柄来操作文件

让我们回到文件操作的话题

if(! open PASSWD, "/etc/passwd"){
    die "How did you get logged in? ($!)";
}
while(){
    chomp;
    ...
}

在这个栗子中可以看到,所谓的行输入操作符<>不过是括住输出信息(文件句柄)的括号而已

#函数入操作符的使用:

“行输入操作符”也叫“钻石操作符”(长得像~)

钻石操作符用来从终端命令行读取参数,并解析文件句柄用于文件操作

使用文件句柄(重定向输出)
print LOG "Hello world\n";  #输出到文件句柄LOG
print STDERR "World hello\n";
改变默认的文件输出句柄

默认情况下,文件输出句柄是STDOUT

Perl使用select来改变默认的文件输出句柄

select函数的作用域,除非显式重新改回原来STDOUT否则将一直延续到程序结束

select MYHANDLE;
print "What are you doing?\n"
print "I am typing with Perl...\n";

现在默认情况下这两句话都被输出到文件句柄MYHANDLE中去了..

特殊变量$|

Perl中的$|变量如果被设置为1,那么之后所有的输出操作将无视缓冲区的存在而“立即刷新缓冲区”,那么输出的内容会被立即发送(如果发送到显示屏就是立即显示)

select LOG;
#|=1;   #不要将LOG的内容保存在缓冲区
select STDOUT;
#...
print LOG "This is something...\n";

以上,比如读取监视某个耗时程序的实时日志


Perl5的新增语法特性

1. open函数有三个参数,实现了参数分离,更安全

open CONFIG, '<', 'dino';
open BEDROCK, '>', '$filename';

2. 三个参数允许指定数据的编码方式

open CONFIG, '<:encoding(UTF-8)', 'dino';
#:encoding(utf-8)简写:utf-8但不推荐简写

3. 自动检测致命错误

use autodie;

4. 使用say来输出

use 5.010;
say "Hello!";   #打印变量并自动在末尾添加一个换行符

5. 标量中的文件句柄

从Perl5.6开始,我们可以把文件句柄存放在标量中,而不必非得使用“裸字(字面量)”
在称为标量之后,文件句柄就可以作为函数参数传递给子程序

my $rocks_fh   #使用词法变量my确保该变量之前是空的
open $rocks_fh, '<', 'rocks.txt'
    or die "Could not open rocks.txt: $!";

或者

open my $rocks_fh, '<', 'rocks.txt'
    or die "Could not open rocks.txt: $!";

在得到保存文件句柄的变量后,直接把原先使用裸字的地方就可以了

while(<$rocks_fh>){
    chomp;
    ...
}

输出信息到文件句柄也可以使用到这个变量,在原先使用裸字的地方使用这个标量便能以适当的方式打开该文件

open my $rocks_fh, '>>', 'rocks.txt'
    or die "Could not open rocks.txt: $!";

foreach my $rock(qw(slate lava granite)){
    say $rocks_fh $rock
}
print $rocks_fh "limestone\n";
print $rocks_fh;

注意,Perl能够自动判断,如果print语句的第一个参数之后没有逗号,就说明它是一个文件句柄(不!要!加!逗!号!)

print $rocks_fh, "limestone\n";    #错误!!(无法判断文件句柄)

一般短小的程序,比如系统管理员的工具脚本,用裸字也没什么不好;不过对于大一点的项目或应用程序来说,使用标量可以精确控制文件句柄的作用域,方便调试和维护

你可能感兴趣的:(Perl,语言)