前面已经提过文件的读写,包括只读模式(open(HANDLE, "filename")),覆盖模式(open(HANDLE,
">filename"))和追加模式(open(HANDLE,
">>filename"))。另一种模式是读写模式:用“+>”或“+<”表示:
- # 打开读写文件
- open (FILE, "+>tmp") || die ("Failed to open tmp");
- print FILE "content";
- $pos = tell(FILE); # tell表示当前位置离文件头的字节数
- print "pos: $pos\n"; # 7
- seek(FILE, 0, 0); # seek第二个参数为偏移的字节数,第三个参数是起始位置,0为从文件头开
- 始移动,1为从当前位置移动,2为从文件末尾移动。
- while (!eof(FILE)) {
- print getc(FILE); # content
- }
- close FILE;
还有一种管道模式:利用管道符(|)打开一个管道,把输入到管道的数据作为另一个进程的标准输入(open
(HANDLE, "|command")),或从管道中读取另一个进程的标准输出(open (HANDLE,
"command|"))。下面是一个例子,程序名为pipeline.pl:
- #!/usr/bin/perl
- $mode = $ARGV[0];
- if ($mode eq "push") {
- if (open(PIPELINE, "|./pipeline.pl push_read")) {
- print PIPELINE "Push to another process\n";
- close(PIPELINE);
- }
- } elsif ($mode eq "push_read") {
- while (<STDIN>) {
- print "=Read=: $_";
- }
- } elsif ($mode eq "pull") {
- if (open (PIPELINE, "./pipeline.pl pull_write|")) {
- while (<PIPELINE>) {
- print "=Read=: $_";
- }
- close (PIPELINE);
- }
- } elsif ($mode eq "pull_write") {
- print "Pull from another process.\n";
- } else {
- die "invalid mode";
- }
输入命令pipeline.pl push得到下列结果:
=Read=: Push to another process
而命令pipeline.pl pull得到:
=Read=: Pull from another process.
利用open函数还可以实现文件的重定向,下面的代码把STDOUT和STDERR的输出都重定向到一个名为tmp的文件中:
- # 重定向标准输出
- open (STDOUT, ">tmp") || die ("Failed to open STDOUT");
- open (STDERR, ">&STDOUT") || die ("Failed to open STDERR");
- print STDOUT "line 1\n";
- print STDERR "line 2\n";
- close STDOUT;
- close STDERR;
上面的代码可以在终端用一行命令简单的完成:foo > tmp 2>&1。其中foo为任意命令。
变量$|用来表示当前输出目标是否使用缓存。如果$|设为1则表示不使用缓存,类似于每次输出后进行一个flush操作:
- $| = 1; # 为STDOUT设置强制输出
- select STDERR;
- $| = 1; # 为STDERR设置强制输出
除了用print和getc来读写字符文件,还可以使用
read,write来读写文件:
- $file = "FILE"; # 使用变量来打开文件
- open ($file, "+) or die ("Failed to open tmp");
- format DATA =
- @<@>>
- 25, abd
- .
- $savedOut = select $file;
- $savedFormat = $~;
- $~ = "DATA";
- write;
- $~ = $savedFormat;
- select $savedOut;
- seek($file, 0, 0);
- read ($file, $num, 2, 0); # read(filevar, result, length, skipval),第一个参数是文件变量,第二个参数是存储读取结果的变量,第三个参数是读取的字符数,第四个参数是读文件之前跳过的字节数(可选)。
- print $num."\n"; # 25
- read ($file, $string, 3);
- print $string."\n"; # abd
- close $file;
- read等同于Unix的fread函数。sysread和syswrite等同于Unix的read和write函数,读写速度更快:
- open (FILE, "+>tmp") || die ("Failed to open tmp");
- syswrite(FILE, 63, 2, 0);
- seek(FILE, 0, 0);
- sysread(FILE, $num, 2, 0);
- print $num."\n"; # 63
当你的系统(如类DOS系统)对文本文件和二进制文件有所区别时可以使用
binmode (filevar)。必须在打开文件后、读取文件前使用。
对目录进行的操作:
- # 目录处理
- mkdir ("mydir"); # 创建目录
- chdir ("mydir"); # 改变当前工作目录
- mkdir ("subdir1"); # 在mydir中创建目录
- mkdir ("subdir2");
- mkdir ("subdir3");
- open (SUBFILE, ">subfile1") and print SUBFILE "sub file 1", close SUBFILE;
- open (SUBFILE, ">subfile2") and print SUBFILE "sub file 2", close SUBFILE;
- chdir (".."); # 回到mydir的父目录
- opendir (MYDIR, "mydir") or die ("open mydir failed");
- while ($file = readdir(MYDIR)) {
- print $file . " | "; # .. | subdir3 | subdir2 | subfile2 | . | subfile1 | subdir1 |
- }
- rewinddir MYDIR; # 让读取目录的位置重置回到开头
- readdir(MYDIR)."\n"; # 忽略第一个子目录
- $location = telldir(MYDIR); # 得到当前读取目录的位置
- print "location: $location\n"; # location: 605303214
- readdir MYDIR; # subdir3
- @files = readdir(MYDIR); # 读取之后所有的文件和子目录名
- print "@files\n"; # subdir2 subfile2 . subfile1 subdir1
- print "End\n" unless readdir(MYDIR); # End
- seekdir(MYDIR, $location); #重新回到之前位置,location必须是telldir的返回值
- print readdir(MYDIR)."\n"; # subdir3
- closedir MYDIR;
mkdir其实可以有第二个参数(mkdir(dirname, permissions))。permissions是一个八进制数,它可以是下列的某个值或某些值的和:
|
权限
|
4000
|
运行时设置用户ID
|
2000
|
运行时设置组ID
|
1000
|
粘贴位
|
0400
|
拥有者读权限
|
0200
|
拥有者写权限
|
0100
|
拥有者执行权限
|
0040
|
组读权限
|
0020
|
组写权限
|
0010
|
组执行权限
|
0004
|
所有人读权限
|
0002
|
所有人写权限
|
0001
|
所有人执行权限
|
文件属性的函数:
- # 重命名一个目录
- rename ("mydir/subdir1", "mydir/subdir6") or print "faied to rename subdir1\n";
- # 移动一个目录
- rename ("mydir/subdir3", "subdir3") or print "failed to rename subdir3\n";
- # 重命名一个文件
- rename ("mydir/subfile1", "mydir/new_subfile") or print "failed to rename subfile1\n";
- # 移动一个文件
- rename ("tmp", "mydir/tmp") or print "failed to rename tmp";
- # 硬链接
- link ("mydir/subfile2", "linkfile") or print "failed to link subfile2\n";
- # 软链接
- symlink ("mydir/subfile2", "shotcut") or print "failed to symlink subfile2\n";
- # 得到软链接指向的文件
- print readlink("shotcut")."\n"; # mydir/subfile2
- # 删除文件(因为实际上是删除文件的一个链接所以得此名)
- print unlink ("mydir/subfile2")."\n"; # 1 返回值为删除文件的个数
- # 改变文件访问权限
- chmod (777, "mydir/tmp"); # chmod(permissions, filelist),permissions的值和mkdir中permissions的取值一样
- # 改变文件的属主
- chown (1, 2, "mydir/tmp"); # chown(usrid, groupid, filelist)。usrid为新属主的ID号,groupid是新的组的ID号
- # 改变文件访问权限掩码,返回当前掩码
- $oldmask = umask(18);
- # 将文件的长度减少到length字节。如果文件长度已经小于length,则不做任何事。
- truncate ("linkfile", 20);
- # 获取文件状态
- @states = stat ("mydir"); # states: 2049 528335 16877 4 1000 1000 0 4096 1322216914 1322216904 1322216904 4096 8
- print "states: @states\n";
- # 将文件看作符号链接并获得状态
- @states = lstat ("shotcut"); # 2049 399968 41471 1 1000 1000 0 14 1322215928 1322215927 1322215927 4096 0
- print "states: @states\n";
stat和lstat的返回值是列表,里面的值依次为:
文件所在设备
内部参考号(inode)
访问权限
硬链接数
属主的(数字)ID
所属组的(数字)ID
设备类型(如果file是设备的话)
文件大小(字节数)
最后访问时间
最后修改时间
最后改变状态时间
I/O操作最佳块大小
分配给该文件的块数
|
其它几个文件相关的函数:
函数名
|
fileno
|
调用语法
|
filedesc = fileno (filevar);
|
解说
|
返回文件的内部UNIX文件描述。参数filevar为文件变量。
|
函数名
|
fcntl
flock
|
调用语法
|
fcntl (filevar, fcntlrtn, value);
flock (filevar, flockop);
|
解说
|
详见同名UNIX函数帮助。
|
与时间相关的函数:
- # 获得当前时间,从1970年1月1日起累计秒数
- print time()."\n"; # 1322218075
- # 把秒数转换成格林威治时间,返回一个列表。元素依次为:
- # 秒\分钟\小时(0~23)\日期\月份(0~11)\年份\星期(0~6)\一年中的日期(0~364)\是否夏令时的标志
- @time = gmtime(time());
- print join("-", @time)."\n"; # 55-47-10-25-10-111-5-328-0
- # 把秒数转换为本地时间,与gmtime相似
- @time = localtime(time());
- print join("-", @time)."\n"; # 55-47-18-25-10-111-5-328-0
- # 改变文件的最后访问时间和最后更改时间
- $accesstime = -A "linkfile"; # 距离现在的天数
- $modifiedtime = -M "linkfile"; # 距离现在的天数
- $accesstime = time() - $accesstime*24*60*60;
- $modifiedtime = time() - $modifiedtime*24*60*60;
- utime ($accesstime, $modifiedtime, "other");
关联数组与文件:
- # 将数组与文件关联
- dbmopen (%hash, "data", 666); # dbmopen (array, dbmfilename, permissions)
- $hash{"a"} = "hello";
- $hash{"b"} = 34;
- dbmclose (%hash);
- dbmopen (%result, "data", 666);
- print $result{"b"}."\n"; # 34
- dbmclose (%result);
- # Perl 5中用tie和untie取代dbmopen和dbmclose
- use Tie::File;
- my @array = ();
- tie(@array, 'Tie::File', "data");
- @array[0] = "tie";
- @array[1] = "untie";
- @array[5] = "data";
- untie (@array); # tie untie data
- tie(@result, 'Tie::File', "data");
阅读(1192) | 评论(0) | 转发(1) |