转自:http://osdev.blogbus.com/logs/66173.html
基础
在Perl中,提供了三种文件句柄:STDIN,STDOUT,STDERR.它们可以由父进程建立的文件或者设备会自动打开.一般使用open函数来建立文件句柄.open函数的语法是只读模式时为:
open (FILEHANDLE,"somename");
其中FILEHANDLE是文件句柄的名字,常用写法是全部大写字母(没有特殊规则,没有特殊前缀).而somename就是你要打开的文件或设备名字.这种方法打开的文件只可进行读取动作.若要打开文件并需要进行写入动作,可以用大于符放到文件名字前面,语法就是覆盖模式了:
open (FILEHANDLE,">somename");
当然,如文件中早存在其他资料,你想在其后增加数据而不对原来数据进行任何动作的话,这个符号可以帮助你:>>,语法就变成了附加模式:
open (FILEHANDLE,">>somename");
另外,文件打开有时候会失败(例如文件不存在,文件名字错了等因素存在).所以在程序里应该对文件打开成功与否进行测试,常用的方法是在open函数调用时利用其返回true/false的值,进行die短路效应测试,它的语法是:
open (FILEHANDLE,">somename") || die "error message:$!";
很多人不知道什么叫"短路效应",就让这个例子来为我们说明吧:譬如打开文件成功,则open函数返回true,此时因为||是OR逻辑,一个为真,则后面的没有必要也没有进行执行动作,所以就忽略(这和电子学上"短路了"一样的道理)了die的执行;而在open函数返回false的时候,因为OR逻辑前一个为假,它必须执行右边的die函数.
或许是die函数太难听了(开玩笑的),perl还提供了一个类似的函数warn,它与die很像:
open (FILEHANDLE,">somename") || warn "error message/n";
安全的打开了文件,那该如何使用呢? 其实使用文件句柄读取数据,就跟从STDIN中读取数据方法相同,举个例子吧:
open (FH,"test.txt");
while(<FH>) {
chomp
print "i saw $_ in the test.txt";
}
如果你用覆盖或者附加方式打开文件(<和<<),而且想用print函数对它进行写入,则语句可以这样写:
print FILEHANDLE "data";
data是你要写入的数据,看清楚,FILEHANDLE和data之间没有逗号,只有空格!
在print函数里,其实我们还可以累赘的写成这样:
print STDOUT "hello,world!/n";
但print默认就是向STDOUT输出.所以此语句变的有点累赘且没必要.
当然,用完了文件,就要关闭:
close(FILEHANDLE);
虽然程序关闭时自动关闭所有开启的文件句柄,但养成检查关闭习惯对良好的程序设计是非常有帮助.
基本的文件操作已经学完,让我们来举个把a.txt文件内容拷贝到b.txt文件的例子吧:
open(INP,"a.txt") || die "can't open a.txt:$!";
open(OUT,"b.txt") || die "can't open b.txt:$!";
while(<INP>) {
print OUT $_;
}
close(IN) || die "can't close a.txt:$!";
close(OUT) || die "can't close b.txt:$!";
打开多文件
如过我们要打开的,并非一个文件,而是多个同后缀的文件.那我们逐一打开它吗?
并不需要!
在UNIX里,可以用echo命令浏览所有符合规则的文件:
echo *.txt
而在perl中,我们可以使用glob函数(也有人叫它做"file glob").它的用法和<STDIN>也很相同:它每次会返回一个在当前目录下,符合条件的文件名.如果所有符合条件的文件名都已经传完,它就返回undef.
测试代码,这里不给出.读者可以自行写一个.
文件测试
新开一个文件时,在安全角度来讲绝对有必要进行同名文件是否已存在的测试.在shell脚本里,可以用-e filename做这件事情,而在Perl中也很像:-e $filename.若文件存在返回真,否则返回假.例子如:
$filename = "a.txt";
if(-e $filename) {
# 这里写存在文件的情况
} else {
# 这里写不存在文件的情况
}
还可以对文件句柄进行可读/可写测试.分别是-r,-w.用法和上面-e $filename一样.如检测一个文件是否可读可写,则可以:
if(-r filename && -w filename)
{
# 这里可进行读写操作.
}
下面给出文件测试和它的意义的列表:
-r 文件或目录可读
-w 文件或目录可写
-x 文件或目录执行
-o 文件或目录归用户所有
-R 文件或目录对真正用户可读
-W 文件或目录对真正用户可写
-X 文件或目录对真正用户执行
-O 文件或目录归真正用户所有
-e 文件或目录存在
-z 文件存在且大小为0
-s 文件或目录存在且不为0(返回字节数)
-f 文件为普通文件
-d 文件为目录
-l 文件为符号链接
-p 文件为命名管道(FIFO)
-S 文件为一个套口(socket)
-b 文件为块特殊文件
-c 文件为字符特殊文件
-t 打开tty控制台的文件句柄
-u 文件或目录是设置用户ID号
-g 文件或目录是设置用户组ID号
-k 文件或目录的sticky位置位
-T 文件是文本文件
-B 文件是二进制文件
-M 以天为单位的存在时间
-A 以天为单位访问时间
-C 以天为单位同代码更改时间
其中大部分是返回true/fals,其中几个例外:
-s:如果文件不是空,返回真.不过这个"真"是文件的长度.(单位是byte.)
-M,-A,-C:返回的是时间,全部用天或1/2天的单位表示,所以36小时被表示为1.5天(如果比较某一个文件比后一个文件早一分钟(或者短时间的比较)的话,你可能要用rangecomparision的方法.).
改头换"名"
为某个文件改名字,可以使用rename函数并进行die短路测试:
rename ("old-filename","new-filename") || die "error message:$!";
删除文件
用unlink函数,可以删除文件,语法是:
unlink ("filename");
打开目录句柄
语法:opendir(DIRECTORY-NAME,"dir") || die "error message:$!";
例子:opendir(DH,"/mp3") || die "打开目录错误:$!";
关闭目录句柄
语法:closedir(DIRECTORY-NAME);
例子:closedir(DH);
创建目录
语法:madir("DIRECTORY-NAME",permission) || die "error message:@!";
其中Permission表示权限的意思.如0777
删除目录
语法:rmdir("DIRECTORY-NAME"); # 当然,也可以进行die短路测试