perl open函数的使用
本文和大家重点讨论一下如何读写Perl文件,主要包括打开、关闭Perl文件,读写Perl文件,Perl文件的状态,命令行参数和打开管道六部分内容,希望通过本文的学习你对读写Perl文件有深刻的认识。
读写Perl文件
一、打开、关闭Perl文件
语法为open(filevar,filename),其中filevar为Perl文件句柄,或者说是程序中用来代表某Perl文件的代号,filename为Perl文件名,其路径可为相对路径,亦可为绝对路径。
open(FILE1,"file1");
open(FILE1,"/u/jqpublic/file1");
打开Perl文件时必须决定访问模式,在Perl中有三种访问模式:读、写和添加。后两种模式的区别在于写模式将原Perl文件覆盖,原有内容丢失,形式为:open(outfile,">outfile");而添加模式则在原Perl文件的末尾处继续添加内容,形式为:open(appendfile,">>appendfile")。要注意的是,不能对Perl文件同时进行读和写/添加操作。
open的返回值用来确定打开Perl文件的操作是否成功,当其成功时返回非零值,失败时返回零,因此可以如下判断:
if(open(MYFILE,"myfile")){
#here'swhattodoifthefileopenedsuccessfully
}
当Perl文件打开失败时结束程序:
unless(open(MYFILE,"file1")){
die("cannotopeninputfilefile1\n");
}
亦可用逻辑或操作符表示如下:
open(MYFILE,"file1")||die("Couldnotopenfile");
当Perl文件操作完毕后,用close(MYFILE);关闭Perl文件。
二、读Perl文件
语句$line=<MYFILE>;从Perl文件中读取一行数据存储到简单变量$line中并把Perl文件指针向后移动一行。<STDIN>为标准输入Perl文件,通常为键盘输入,不需要打开。
语句@array=<MYFILE>;把Perl文件的全部内容读入数组@array,Perl文件的每一行(含回车符)为@array的一个元素。
三、写Perl文件
形式为:
open(OUTFILE,">outfile");
printOUTFILE("Hereisanoutputline.\n");
注:STDOUT、STDERR为标准输出和标准错误Perl文件,通常为屏幕,且不需要打开。
四、判断Perl文件状态
1、Perl文件测试操作符
语法为:-opexpr,如:
if(-e"/path/file1"){
printSTDERR("Filefile1exists.\n");
}
Perl文件测试操作符
例:
unless(open(INFILE,"infile")){
die("Inputfileinfilecannotbeopened.\n");
}
if(-e"outfile"){
die("Outputfileoutfilealreadyexists.\n");
}
unless(open(OUTFILE,">outfile")){
die("Outputfileoutfilecannotbeopened.\n");
}
等价于
open(INFILE,"infile")&&!(-e"outfile")&&
open(OUTFILE,">outfile")||die("Cannotopenfiles\n");
五、命令行参数
象C一样,Perl也有存储命令行参数的数组@ARGV,可以用来分别处理各个命令行参数;与C不同的是,$ARGV[0]是第一个参数,而不是程序名本身。
$var=$ARGV[0];#第一个参数
$numargs=@ARGV;#参数的个数
Perl中,<>操作符实际上是对数组@ARGV的隐含的引用,其工作原理为:
1、当Perl解释器第一次看到<>时,打开以$ARGV[0]为Perl文件名的Perl文件;
2、执行动作shift(@ARGV);即把数组@ARGV的元素向前移动一个,其元素数量即减少了一个。
3、<>操作符读取在第一步打开的Perl文件中的所有行。
4、读完后,解释器回到第一步重复。
例:
@ARGV=("myfile1","myfile2");#实际上由命令行参数赋值
while($line=<>){
print($line);
}
将把Perl文件myfile1和myfile2的内容打印出来。
六、打开管道
用程序的形式也可以象命令行一样打开和使用管道(ex:ls>tempfile)。如语句open(MYPIPE,"|cat>hello");打开一个管道,发送到MYPIPE的输出成为命令"cat>hello"的输入。由于cat命令将显示输入Perl文件的内容,故该语句等价于open(MYPIPE,">hello");用管道发送邮件如下:
open(MESSAGE,"|maildave");
printMESSAGE("Hi,Dave!YourPerlprogramsentthis!\n");
close(MESSAGE);
说明:就会把在filehandle的数据输入给unix的指令来作处理。
实例1 发邮件
$mailprog="/usr/ucb/mail"; #unix系统上的寄信程序(一定要加绝对路径)
$who="mqingyi@126.com";
$open(file,"|$mailprog $who")||die"打开失败\n";
print file "I love you!\n";
print file "I want to see you.\n";
close(file);
就会通过unix系统mail的程序,将FILE这个FILEHANDLE的数据内容寄给$who这个变量所指定的收信人。 我们可以利用open这个函数来设计一个来信批评CGI应用程序,在本书中的下一章中会有详细的介绍。
==============================
实例2 显示系统进程数
#!/usr/bin/perl
# returns number of open processes from 'ps' output
open(PROCS,'/bin/ps ax |');
while () {
$procs++;
}
close(PROCS);
$procs--;
print $procs;
===============================
#下面的小例子 仅仅是验证perl | +unix命令的可能性!
[root@localhost perl]# cat catmai
#!/usr/bin/perl
$catprog="/bin/cat";
open(file,"|$catprog >new")||die"打开失败\n";
print file "i love you\n";
print file "i want to see you\n";
close(file);
[root@localhost perl]# cat new
i love you
i want to see you
[root@localhost perl]#
打开管道
在 C 中,当你想用标准 I/O 库打开一个文件时,你要用 “fopen” 函数,当你
想打开一个管道时,你要用 “popen” 函数。但是在 shell 中,你只是用不同
的重定向字符。对于 Perl 也是如此。”open”
的调用方法一样,只是参数不同了。
如果以管道符号开头,”open” 启动一个新的命令,打开一个可写文件句柄通向
这个命令。你可以向这个句柄中写入内容,而你所写的将出现在这个命令的标准
输出里。例如:
open(PRINTER, “| lpr -Plp1″) || die “can’t run lpr: $!”;
print PRINTER “stuff\n”;
close(PRINTER) || die “can’t close lpr: $!”;
如果末尾的字符是一个管道时,你启动一个新的命令,打开一个通向这个命令的
可读文件句柄。这使得这个命令写入标准输出的内容可以在你的句柄中读到的。
open(NET, “netstat -i -n |”) || die “can’t fork netstat: $!”;
while () { } # do something with input
close(NET) || die “can’t close netstat: $!”;
当你试图打开一个通向或者来自不存在的命令的管道时会发生什么呢?如果可
能,Perl 会检测到命令失败,然后照常设置 $!。但是如果命令中包含特殊 的
shell 字符,例如 “>” 或者 “*”,称为“metacharacters”,Perl 不
会直接执行命令。取而代之的是,Perl 运行 shell,它来试图运行命令。这意
味着是 shell 得到错误指示。在这种情况下,如果 Perl 根本不能运行
shell,”open” 只会指示一个错误。参考 “How can I capture STDERR from an
external command?” in perlfaq8 了解如何应付这个问题。在 perlipc
中也有回答。
如果你想打开双向管道,IPC::Open2 可以处理。参考 “Biderectional
Communication with Another Process” in perlipc。
负号文件
和标准 shell 实用程序一样,Perl 的 “open” 函数对于只是一个负号的文件
名的处理方法是特殊的。如果你以可读方式打开负号,实际上是访问标准输入。
如果以可写方式打开,实际上是访问标准输出。
如果负号能用作默认的输入或者输出,当你打开一个通向或者来自负号的管道会
发生什么呢?它会运行什么默认的命令?仅仅是和你现在运行的脚本一样!事实
上在 “open” 背后秘密进行了一次 “fork”。更详细内容请参考 “Safe Pipe
Opens” in perlipc。
2.打开管道
用open函数也可像命令行一样,打开和使用管道.
语法为:
open(MYVAR, "mode");
mode有如下两种模式:
"|command" 表示对MYVAR的输出相当于对command的输入.
"command|" 表示command的输出作为对MYVAR的输入.
例如:
open(FILE1, "who|") or die("Could not open file.\n");
while ($line = )
{
print $line;
}
3.文件重定向
许多UNIX shell可以把标准输出文件(STDOUT)和标准错误文件(STDERR)都重定向到同一个文件.
例如在BASH中,命令`$ foo > file1 2>&1`把输出到标准输出和标准错误的内容存贮到文件file1中.
用open函数可以实现文件重定向.
如以上命令可以用如下命令实现:
open (STDOUT, ">file1") || die ("open STDOUT failed");
open (STDERR, ">&STDOUT") || die ("open STDERR failed");
文章出处:飞诺网(www.diybl.com):http://www.diybl.com/course/4_webprogram/cgi/perl/20090820/169233.html
一.文件操作
1.打开文件
用open函数可将文件句柄与某文件联系起来,提供访问文件的接口,即打开文件.
语法为:
open(FILEVAR, "filepath");
filepath可以有如下三种模式:
"filepath" 以只读模式打开文件.
">filepath" 以写模式打开文件.
">>filepath" 以追加模式打开文件,写和追加的区别在于写模式将原文件覆盖,而追加模式则在文件末尾处添加内容.
"+>filepath" 以读和写方式打开文件.
"+>>filepath" 以读和追加方式打开文件.
open的常见用法如下:
if (open(MYFILE, "myfile"))
{
# here's what to do if the file opened successfully
}
当文件打开失败时结束程序
unless (open (MYFILE, "file1"))
{
die ("cannot open input file file1\n");
}
亦可用逻辑或操作符表示如下:
open (MYFILE, "file1") || die ("Could not open file");
2.打开管道
用open函数也可像命令行一样,打开和使用管道.
语法为:
open(MYVAR, "mode");
mode有如下两种模式:
"|command" 表示对MYVAR的输出相当于对command的输入.
"command|" 表示command的输出作为对MYVAR的输入.
例如:
open(FILE1, "who|") or die("Could not open file.\n");
while ($line = )
{
print $line;
}
3.文件重定向
许多UNIX shell可以把标准输出文件(STDOUT)和标准错误文件(STDERR)都重定向到同一个文件.
例如在BASH中,命令`$ foo > file1 2>&1`把输出到标准输出和标准错误的内容存贮到文件file1中.
用open函数可以实现文件重定向.
如以上命令可以用如下命令实现:
open (STDOUT, ">file1") || die ("open STDOUT failed");
open (STDERR, ">&STDOUT") || die ("open STDERR failed");
4.读取文件
语句$line = ;从文件中读取一行数据存储到简单变量$line中并把文件指针向后移动一行.
语句@array = ;把文件的全部内容读入数组@array,文件的每一行(含回车符)为@array的一个元素.
注:为标准输入文件,通常为键盘输入,不需要打开.
例如:
open(FILE1, "testfile") or die("Could not open file.\n");
@line = ;
foreach $message (@line)
{
print $message;
}
此外perl还提供以下几个系统读函数.
函数read
调用语法:
read (filevar, result, length, skipval);
read函数设计得与UNIX的fread函数等效,可以读取任意长度的字符存入一个简单变量.
filevar表示文件变量
result表示存贮结果的简单变量
length表示读取的字节数
skipval(可选项),指定读文件之前跳过的字节数.
返回值为实际读取的字节数,如果已到了文件末尾,则返回零.如果出错,则返回空串.
函数sysread
调用语法:
sysread (filevar, result, length, skipval);
更快的读取数据,与UNIX函数read等效,参数与read相同.
函数getc(读取单个字符)
调用语法:
$char = getc (infile);
从文件中读取单个字符。
函数binmode(读取二进制文件)
调用语法:
binmode (filevar);
当你的系统(如类DOS系统)对文本文件和二进制文件有所区别时使用.必须在打开文件后,读取文件前使用.
5.写入文件
写入文件通常用print,printf和write这三个函数.
print是这三个函数中最简单的,它向指定的文件输出,如果未指定,则输出到当前缺省文件中.
如:
print ("Hello, there!\n");
print OUTFILE ("Hello, there!\n");
第一句输出到当前缺省文件中,若未调用select,则为STDOUT.
第二句输出到由文件变量OUTFILE指定的文件中.
printf函数先格式化字符串再输出到指定文件或当前缺省文件中.
如:
printf OUTFILE ("you owe me %8.2f", $owing);
此语句取出变量$owing的值并替换掉串中的%8.2f,%8.2f是域格式的例子,把$owing的值看作浮点数.
printf的域格式表如下:
%c 单个字符
%d 十进制整数
%e 科学计数法形式的浮点数
%f 普通形式(定点)浮点数
%g 紧缩形式浮点数
%o 八进制整数
%s 字符串
%u 无符号整数
%x 十六进制整数
域格式的注意事项:
A.在格式d,o,u或x中,如果整数值较大或可能较大,可加个l字符,意为长整型,如%ld.
B.%字符后加正整数表示该域的最小宽度,如果宽度不足,则向右对齐,前面用空格补足.如果该正整数以数字0打头,则补足字符为0.若%字符后为负整数,则结果向右对齐.
C.浮点数域值(%c,%f和%g)中可以指定小数点前后的宽度,如%8.3f意为总宽度为8个字符,小数点后(即小数部分)为3个字符,多出的小数部分四舍五入.
D.在整数,字符或字符串的值域中使用如上的小数形式n.m,n为总宽度,m为输出结果的最大宽度,这样就保证了输出结果前至少有n-m个空格.
write函数使用输出格式把信息输出到文件中.
此外perl还提供以下系统写函数.
函数syswrite
调用语法:
syswrite (filevar, data, length, skipval);
更快的写入数据,与UNIX函数write等效.
filevar:将要写入的文件
data:存贮要写入数据的变量
length:要写入的字节数
skipval写操作之前跳过的字节数
最后注意:
有些操作系统在对文件写入数据时,会先把数据拷贝到一片特殊的内存即缓冲区中,接下来的输出操作继续写入缓冲区直到写满.当缓冲区满了,就把全部数据实际写入.
象这样先写入缓冲区再把整个缓冲区的内容输出比每次都实际输出所花费的时间要少得多,因为一般来说,I/O比内存操作慢得多.
在perl中,如果要使当前缺省文件的输出不进行缓冲,可对$|赋一个非0值.
select (OUTFILE);
$| = 1;
这样就关闭了对OUTFILE文件写入的缓冲.
6.关闭文件
close函数可用来关闭已打开的文件.
当用close关闭管道,即重定向的命令时,程序等待重定向的命令结束.
如:
open (MYPIPE, "cat file*|");
close (MYPIPE);
当关闭此文件变量时,程序暂停运行,直到命令cat file*运行完毕.
7.select函数
select函数将通过参数传递的文件变量指定为新的当前缺省文件.
如:
select (MYFILE);
这样,MYFILE就成了当前缺省文件,当对print,write和printf的调用未指定文件时,就输出到MYFILE中.
8.eof函数
eof函数查看最后一次读文件操作是否为文件最后一个记录.如果是,则返回非零值;如果文件还有内容,返回零.
一般情况下,对eof的调用不加括号,因为eof和eof()是等效的.但与<>操作符一起使用时,eof和eof()就不同了.
9.文件定位
tell函数和seek函数配合使用,可轻松实现文件内部的定位.
tell函数的调用格式如下:
tell (filevar);
用于返回从文件头到当前位置的距离。
seek函数的调用格式如下:
seek (filevar, distance, relative_to);
distance表示移动的字节数,正数向前移动,负数往回移动.
reletive_to的值可为0,1或2.为0时,从文件头开始移动;为1时,相对于当前位置移动;为2时,相对于文件末尾移动.
命令运行成功返回真,失败则返回零.
注意:
A.seek和tell不能用于指向管道的文件变量。
B.seek和tell中文件变量参数可使用表达式。
二.目录操作
1.新建目录
函数mkdir
调用语法:
mkdir (dirname, permissions);
dirname,将要创建的目录名,可以为字符串或表达式
permissions,8进制数,指定目录的访问权限,其值和意义见下表,权限的组合方法为将相应的值相加.
4000 运行时设置用户ID
2000 运行时设置组ID
1000 粘贴位
0400 拥有者读权限
0200 拥有者写权限
0100 拥有者执行权限
0040 组读权限
0020 组写权限
0010 组执行权限
0004 所有人读权限
0002 所有人写权限
0001 所有人执行权限
2.改变当前工作目录
函数chdir
调用语法:
chdir (dirname);
改变当前工作目录,参数dirname可以为字符串,也可以为表达式.
3.打开目录
函数opendir
调用语法:
opendir (dirvar, dirname);
打开目录,与其它函数合用,可查看某目录中文件列表.
dirvar,目录变量,与文件变量类似.
dirname,目录名,可为字符串或表达式.
成功返回真值,失败返回假.
4.读取目录
函数readdir
调用语法:
readdir (mydir);
赋给简单变量时,每次赋予一个文件或子目录名,对数组则赋予全部文件和子目录名.
5.定位目录列表
函数telldir
调用语法:
location = telldir (mydir);
象在文件中前后移动一样,telldir和下面的seekdir用于在目录列表中前后移动.
函数seekdir
调用语法:
seekdir(mydir, location);
location必须为telldir返回的值。
函数rewinddir
调用语法:
rewinddir (mydir);
将读取目录的位置重置回开头,从而可以重读目录列表.
6.关闭目录
函数closedir
调用语法:
closedir (mydir);
关闭打开的目录.
7.删除目录
函数rmdir
调用语法:
rmdir (dirname);
删除空目录,成功则返回真,失败返回假.
三.文件属性操作
1.文件重定位函数
函数rename
调用语法:
rename (oldname, newname);
改变文件名或移动到另一个目录中,参数可为字符串或表达式.
2.链接和符号链接函数
函数link
调用语法:
link (newlink, file);
创建现有文件的链接--硬链接,file是被链接的文件,newlink是被创建的链接.
成功返回真,失败返回假.
当删除这两个链接中的一个时,还可以用另一个来访问该文件.
函数symlink
调用语法:
symlink (newlink, file);
创建现有文件的符号链接,参数和返回值同上.
当原文件被删除(如:被unlinke函数删除),则被创建链接不可用.
函数readlink
调用语法:
filename = readlink (linkname);
如果linkname为符号链接文件,返回其实际指向的文件,否则返回空串.
函数unlink
调用语法:
num = unlink (filelist);
删除文件,参数为文件名列表.
返回值为实际删除的文件数目.
此函数之所以叫unlink而不叫delete是因为它实际所做的是删除文件的链接.
3.文件许可权函数
函数chmod
调用语法:
chmod (permissions, filelist);
改变文件的访问权限.
permissions为将要设置的权限,filelist为欲改变权限的文件列表.
函数chown
调用语法:
chown (userid, groupid, filelist);
改变文件的属主.
userid,新属主的(数字)ID号.
groupid,新的组(数字)ID号,-1为保留原组.
filelist,欲改变属主的文件列表.
函数.umask
调用语法:
oldmaskval = umask (maskval);
设置文件访问权限掩码,返回值为当前掩码.
4.其它属性函数
函数truncate
调用语法:
truncate (filename, length);
将文件的长度减少到length字节,如果文件长度已经小于length,则不做任何事.
其中filename可以为文件名,也可以为文件变量.
函数stat
调用语法:
stat (file);
获取文件状态,参数file可为文件名也可为文件变量.
返回列表元素依次为:
* 文件所在设备
* 内部参考号(inode)
* 访问权限
* 硬链接数
* 属主的(数字)ID
* 所属组的(数字)ID
* 设备类型(如果file是设备的话)
* 文件大小(字节数)
* 最后访问时间
* 最后修改时间最后改变状态时间
* I/O操作最佳块大小
* 分配给该文件的块数
函数lstat
调用语法:
lstat (file);
与stat类似,区别是将file看作是符号链接.
函数utime
调用语法:
utime (acctime, modtime, filelist);
改变文件的最后访问时间和最后更改时间.
函数fileno
调用语法:
filedesc = fileno (filevar);
返回文件的内部UNIX文件描述,参数filevar为文件变量.