文章教程

8.4文件的高级操作

9/17/2020 9:31:19 PM 人评论 次浏览

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()语句的用法完全一样,这里不再重复举例。

教程类别