8.4 文件的高级操作
除了对文件进行复制、删除、查找等常见操作外,利用PHP中的一些函数还可以对文件执行高级一点的操作,如修改文件的属性、锁定文件、包含文件等。
8.4.1 处理文件的锁定
或者都没有被保存?在实际应用中,经常会碰到两个或多个用户程序同时读写一个文件等类似的问题。如果一个文件被某个用户的程序打开写入一些内容,同时,另外一个用户也打开这个文件,向其中写入数据,那么文件的最终内容会是怎样的?哪个用户的程序写入的数据将被文件系统保存?还是两个写入的数据都会被保存?
为了解决这样的问题,保证文件中数据的完整有效,在操作文件时,需要对文件进行加锁操作。PHP通过函数flock完成对文件的锁定操作,语法如下。
bool flock($fp, int $operation [,int &wouldblock]);
该函数的第1个参数是文件的句柄;第2个参数表示锁定种类,它是一个常量;第3个参数是可选的,如果锁定会阻塞(即需要等待),该参数设置为TRUE。如果成功锁定了文件,该函数会返回TRUE,否则返回FALSE。下面重点介绍函数flock()的第2个参数,它代表了锁定文件的种类,表8-2列举了参数$operation的可能取值。
表8-2 函数flock()锁定种类参数$operation的取值
代码8-12是一个对文件进行锁定的示例小程序。
代码8-12 对文件进行锁定8-12.php
01 <?php 02 $fp = fopen($_SERVER['DOCUMENT_ROOT']."/../data/lock_test.txt",'w'); 03 04 flock($fp,LOCK_EX); // 写锁定,独享锁定文件lock_test.txt 05 fwrite($fp,"Write Some Words...."); 06 flock($fp,LOCK_UN); // 释放对文件lock_test.txt 的锁定 07 08 fclose($fp); 09 ?>
【代码解析】代码第04行使用参数LOCK_EX实现了对文件的独享锁定,使用锁定后,不要忘记再用参数LOCK_UN释放锁定,如第06行代码所示。
注意 如果在程序中,对某个文件操作时使用了函数flock()进行锁定,那么要对程序中所有对这个文件有操作的地方使用函数flock()进行锁定,否则锁定就无效。
8.4.2 更改文件的属性
更改文件的属性,主要涉及更改文件的模式、所有者和更改文件的组。通常,在UNIX系统下讨论这些问题才更有意义,相关函数如下。
·函数chgrp($filename,$group),用来将文件$filename所属的组改为$group(可以使用组名或组ID)。如果更改成功,函数返回TRUE,否则返回FALSE。
·函数chmod($filename,$mode),将文件$filename的模式改为$mode。这里的模式是指可读、可写和可执行。例如,在UNIX系统中,如果文件的模式为0777,表示所有用户对该文件可读、可写并且可执行。如下为该函数的一个示例代码。这行代码将文件/home/log/del.sh改为所有人可读、可写、可执行。
chmod( “/home/log/del.sh ”, 0777);
·函数chown($filename,$user),将文件$filename的所有者改为$user。如果更改成功,函数返回TRUE,否则函数返回FALSE。如下为该函数的一个示例代码。这行代码将文件/etc/passwd的所有者改为root。
chown( “/etc/passwd ”,”root ”);
8.4.3 获取文件时间属性
PHP提供了3个函数获取文件的时间属性,如文件的上次访问时间、文件的最后修改时间、取得文件的inode修改时间。这3个函数如下所述。
·函数fileatime(),返回文件上次被访问的时间,如果出错则返回FALSE,时间以UNIX时间戳的方式返回。
·函数filemtime(),返回文件上次被修改的时间,出错时返回FALSE,时间以UNIX时间戳的方式返回。
·函数filectime(),返回文件上次inode被修改的时间,如果出错则返回FALSE,时间以Unix时间戳的方式返回。inode是UNIX系统中的一个概念,其中文含义可以理解为索引节点,用来存放档案及目录的基本信息,包括时间、档案名、使用者及群组等。
代码8-13演示了这些函数的用法。
代码8-13 获取文件时间属性8-13.php
01 <?php 02 $last_access = fileatime("data.txt"); // 获取文件的上次访问时间 03 echo " 文件最后的访问时间是:"; 04 echo date("l F d, Y", $last_access); 05 echo "<br>"; 06 echo "<br>"; 07 08 $last_modify = filemtime("data.txt"); // 获取文件的上次修改时间 09 echo " 文件最后的修改时间:"; 10 echo date("l F d, Y", $last_modify); 11 echo "<br>"; 12 echo "<br>"; 13 14 $last_modify_inode = filectime("data.txt"); // 获取文件上次inode 被修改的时间 15 echo " 文件最后的改变时间:"; 16 echo date("l F d, Y", $last_modify_inode); 17 echo "<br>"; 18 echo "<br>"; 19 ?>
【代码解析】代码8-13在当前目录下获取文件data.txt的时间属性,因为这些函数返回的时间值是UNIX时间戳,所以应先将时间戳格式化后再输出。代码8-13的执行结果如图8-14所示。
图8-14 获取文件的时间属性
8.4.4 通过HTTP协议打开文件
通过HTTP协议打开文件,就是使用函数fopen()打开一个远程文件,这和使用函数fopen()打开一个本地文件几乎没有区别。代码8-14说明了如何通过HTTP协议打开文件。
代码8-14 通过HTTP协议打开文件8-14.php
01 <?php 02 echo "<H3> 通过http 协议打开文件</H3>"; 03 echo "<br/>"; 04 05 if(!($file=fopen("http://localhost/ch06/server_data.txt","r")))// 通过HTTP 协议打开文件 06 { 07 echo " 文件不能打开"; 08 exit; 09 } 10 while(!feof($file)) 11 { 12 $line = fgetss($file, 255); // 按行读取文件中的内容 13 echo $line; 14 echo "<br/>"; 15 } 16 17 fclose($file); // 关闭文件的句柄 18 ?>
【代码解析】代码首先通过函数fopen()打开本地HTTP服务路径下ch06目录中的server_data.txt文件,如代码第5行所示,这里也可以通过HTTP协议打开一个远程服务器的文件。如果找到该文件,则在没有达到文件末尾时,循环读出文件内容,如代码第10~15行所示。注意,这里使用函数fgetss()读取文件内容,该函数语法如下。
string fgetss(resource $handle)
函数fgetss()从参数$handle所指文件中读取一行内容,并将其中的HTML标记过滤掉,事实上,这也是它和函数fgets()的唯一不同之处。假如在程序所指目录下(代码第5行所示)存在一个名为server_data.txt的文件,其中内容如图8-15所示,那么8-14.php的执行结果就会如图8-16所示。
从图8-15和图8.16中可以看出,使用函数fopen()打开了一个文件,并且使用函数fgetss()获取文件内容后,原文件中的HTML标记都被删除。
图8-15 服务器上某文件内容
图8-16 通过HTTP协议打开文件后输出其内容
8.4.5 包含指定的文件到当前文件
这一小节要介绍两个比较重要的PHP语句——include()和require(),事实上,它们属于PHP流程控制方面的内容,之所以放在这里讲述,是因为它们涉及文件和函数的概念。
include()语句用来在当前文件中包含并运行指定文件。当一个文件被包含时,被包含文件中可用的任何变量、函数在被调用的文件中也都可用,所有在包含文件中定义的变量、函数或类都具有全局作用域。
下面举一个简单例子说明include()的用法,首先创建如代码8-15所示的PHP程序。
代码8-15 一个定义了变量和函数的PHP程序8-15.php
01 <?php 02 define(PI,3.14); // 定义PI 常量 03 04 $rad = 100; 05 $str = "include 的用法"; 06 07 function cal_area($radius) // 定义计算面积的函数 08 { 09 $area = PI * $radius * $radius; 10 return $area; 11 } 12 ?>
【代码解析】程序8-15.php定义了一个常量PI、两个变量和一个函数,该PHP程序将被包含在另外一个PHP文件中。
接下来创建另外一个PHP程序,如代码8-16所示。
代码8-16 使用include()的PHP程序8-18.php
01 <?php 02 include("8-15.php"); // 包含进来指定的文件 03 04 echo $str; 05 echo "<br/>"; 06 echo "<br/>"; 07 08 $area = cal_area($rad); // 调用文件中的函数 09 echo " 在8-15.php 中计算半径为".$rad." 圆面积是:".$area; 10 ?>
【代码解析】代码首先使用include()语句,将此前创建的文件8-15.php包含在当前程序8-18.php中。此时,在8-15.php中定义的变量、函数都将在8-16.php中生效,凡是在8-15.php中定义的变量、函数都可以在8-16.php中使用。但需要注意的是这些变量和函数作用域是全局的,执行8-18.php,如果一切正常,将看到如图8-17所示的结果。
图8-17 在程序中使用include()语句
从这个执行结果可以看出,在8-16..php中输出的变量$str是在8-15中定义的,它在8-16.php中正常输出。然后8-16.php调用在8-15.php中定义的函数cal_area()计算了圆的面积,并将结果输出到页面。
在PHP程序中,除了使用include()包含指定的文件之外,还可以使用语句require()包含指定的文件到当前文件中。这两种结构用法完全一样,不同之处是它们对错误的处理,include()产生一个警告而require()则会导致一个致命错误。换句话说,如果想在遇到丢失文件时停止处理页面,就要使用require()。而这种情况下使用include(),脚本会继续运行。
和include()、require()对应的还有另外两个用来包含指定文件的语句,它们是include_once()和require_once()。它们和include()、require()语句类似,唯一区别是如果该文件中的代码已经被包含了,不会再次包含。它们的用法和include()语句的用法完全一样,这里不再重复举例。
共有条评论 网友评论