第1篇 PHP基础应用

第1章 文件系统与文本数据操作

在程序设计中,文件是一个很重要的对象,Web编程也不例外。文件的操作在很多Web系统中一直都是被反复用到的。在实际应用中经常会遇到对文件和目录的创建、修改、删除等操作。本章将主要介绍如何使用PHP对文件系统以及文本数据进行操作。

1.1 PHP中目录操作详解

所谓目录,也称文件夹,是操作系统用于管理文件的群组。在PHP中,常见的目录操作包括打开目录、关闭目录、读取目录中的文件、创建目录以及删除目录等。

1.1.1 打开目录

PHP中使用opendir函数打开一个目录。opendir函数将返回一个资源对象,用于存储当前目录资源,语法格式如下所示。

        opendir(string path)

其中,path是目录所在的路径。通常,为了确保程序的正确性,在打开目录之前要使用is_dir函数判断路径的有效性。is_dir函数的语法格式如下所示。

        bool is_dir(string path)

以下代码是一个打开目录的例子。

        <?php
        $dir = "test/";                                       //设置目录为test
        if(is_dir($dir))                                      //如果目录存在,则打开
            $dir_res = opendir($dir);
        else                                                  //否则输出错误信息
            echo "目录不存在或者不是一个有效目录";
        ?>

1.1.2 关闭目录

PHP中使用closedir函数关闭目录,其语法格式如下。

        void closedir(dir_resource)

其中dir_resource是使用opendir函数打开目录时返回的资源对象。以下代码用于关闭上面打开的目录。

        <?php
        closedir($dir_res);                               //关闭目录
        ?>

1.1.3 读取目录中的文件

PHP中使用readdir函数读取目录中的文件并返回文件名,其语法格式如下所示。

        string readdir(dir_resource)

其中dir_resource是使用opendir函数打开目录时返回的资源对象。该函数按照文件系统中的文件排序返回文件名。每次执行读取下一个文件并返回一条记录。以下代码是一个读取目录中文件的例子。

        <?php
        $dir = "files/";                                  //定义路径
        $dir_res = opendir($dir);                         //打开目录
        while($filen=readdir($dir_res))                   //循环读取目录中的文件
        {
            echo $filen."<br>" ;
        }
        closedir($dir_res)                                //关闭目录
        ?>

运行结果如下所示。

        .
        ..
        class.php
        test.php
        test1.php

从运行结果可以看出,除了文件夹中的文件以外还包含有“.”和“..”两个文件夹。其中,“.”用于表示当前目录,“..”用于表示上一级目录。

1.1.4 创建目录

PHP中使用mkdir函数创建目录,其语法格式如下所示。

        bool mkdir(string pathname)

其中pathname是要创建的目录地址。以下代码是一个创建目录的例子。

        <?php
        $dir = "Test/";
        if(!is_dir($dir))                                 //如果目录不存在则创建
            mkdir($dir);
        ?>

执行后可以看到,程序在当前页面所在的目录下创建了一个新的名为“Test”的目录。

1.1.5 删除目录

PHP中使用rmdir函数创建目录,其语法格式如下所示。

        bool rmdir(string pathname)

其中pathname是要删除的目录地址。需要注意的是删除目录的时候,该目录必须是空的。以下代码是一个删除目录的例子。

        <?php
        $dir = "Test/";
        if(is_dir($dir))                             //如果目录存在则删除
            rmdir($dir);
        ?>

执行后可以看到,在前面用mkdir函数创建的名为“Test”的目录被删除了。

1.2 PHP中文件操作详解

在文件系统中,一个目录可能会包含很多文件。在实际应用中,文件的操作比目录的操作更普遍。本节将主要介绍PHP中的文件操作。需要注意的是,在PHP中文件的概念不仅包括本地文件,还包括远程文件。本节中所讲述的文件路径既可以是一个本地的路径,也可以是一个远程的网址。

1.2.1 打开文件

PHP中使用fopen函数打开一个文件。fopen函数将返回一个资源对象,用于存储当前文件资源,其语法格式如下所示。

        fopen(string filename, string mode)

其中,filename是文件的文件名及其所在路径,mode是文件的打开模式。mode的可能值如表1-1所示。

表1-1 fopen函数的mode参数

1.2.2 关闭文件

PHP中使用fclose函数关闭文件,其语法格式如下所示。

        void fclose(file_resource)

其中 file_resource 是使用 fopen 函数打开文件时返回的资源对象。以下代码实现了一个打开关闭文件的操作。

        <?php
        $file = fopen("Test\\file.txt", "w");                      //打开文件
        fclose($file);                                             //关闭文件
        ?>

1.2.3 读取文件

PHP提供了多种读取文件的方法。这里仅介绍最常见的3种。

1.读取文件中的一个字符

函数fgetc用来读取文件中的一个字符,语法格式如下所示。

        string fgetc(file_resource)

其中 file_resource 是使用 fopen 函数打开文件时返回的资源对象。该函数返回文件中的一个字符并将指针移动到下一个字符。以下代码是一个使用fgetc函数读取文件的例子。

        <?php
        $file = fopen("Test\\file.txt", "r");                      //打开文件
        echo fgetc($file);                                         //读取文件中的一个字符
        fclose($file);                                             //关闭文件
        ?>

从该程序的运行结果可以看出,文件中的第一个字符被输出了。2.读取文件中的一行

函数fgets用来读取文件中的一行,语法格式如下所示。

        string fgets(file_resource)

其中 file_resource 是使用 fopen 函数打开文件时返回的资源对象。该函数返回文件中的一行并将指针移动到下一行。以下代码是一个使用fgets函数读取文件的例子。

        <?php
        $file = fopen("Test\\file.txt", "r");                     //打开文件
        echo fgets($file);                                         //读取文件中的一行
        fclose($file);                                             //关闭文件
        ?>

从该程序的运行结果可以看出,文件中的第一行被输出了。fgets是在实际应用中最常用到的一种方法,通常通过循环读取的方式获得文件的全部内容,并且可以方便地对文件的每一行进行处理。

3.读取文件中任意长字符

函数fread用来读取文件中任意长字符,语法格式如下。

        string fread(file_resource, int length)

其中file_resource是使用fopen函数打开文件时返回的资源对象,length是要读取的字符长度。以下代码是一个使用fread函数读取文件的例子。

        <?php
        $file = fopen("Test\\file.txt", "r");
        echo fread($file, 20);                                     //读取文件中的前20个字符
        fclose($file);
        ?>

从该程序的运行结果可以看出,文件中的前20 个字符被输出了。需要注意的是如果指定的length参数超过了文件的长度,文件的全部内容将被返回。

通常结合使用fread函数和filesize函数来获取文件的全部内容。filesize函数用于返回文件大小的字节数,语法格式如下。

        int filesize(string filename)

其中,filename 是文件的文件名及其所在路径。以下代码是一个返回文件所有内容的例子。

        <?php
        $filename = "Test\\file.txt";
        $file = fopen($filename, "r");
        $filesize = filesize($filename);                          //获取文件长度
        echo fread($file, $filesize);                             //获取文件全部内容
        fclose($file);
        ?>

1.2.4 写入文件

PHP中使用fwrite函数将数据写入文件,语法格式如下。

        int fclose(file_resource, string str [,int length])

其中file_resource是使用fopen函数打开文件时返回的资源对象,str是要写入文件的字符串,length是一个可选的指定长度的参数。如果指定length,则只将str的前length长度的字符写入文件。以下代码实现了一个写文件的操作。

        <?php
        $filename = "Test\\file.txt";
        $file = fopen($filename, "w");                            //以写模式打开文件
        fwrite($file, "Hello, world!\n");                         //写入第一行
        fwrite($file, "This is a test!\n");                       //写入第二行
        fclose($file);                                            //关闭文件
        ?>

上面的代码运行后在file.txt中写入了两行,如下所示。

        Hello, world!
        This is a test!

1.2.5 删除文件

PHP中使用unlink函数删除文件,语法格式如下所示。

        bool unlink(string filename)

其中,filename是文件的文件名及其所在路径。以下代码实现了一个删除文件的操作。

        <?php
        $filename = "Test\\file.txt";
        unlink($filename);                                    //删除文件
        ?>

上面的代码运行后,文件file.txt将被删除。

1.2.6 复制文件

PHP中使用copy函数复制文件,语法格式如下。

        bool copy(string filename1, string filename2)

其中,filename1 是源文件的文件名及其所在路径,filename2 是目标文件的文件名及其所在路径。该函数的执行结果是将filename1复制到filename2。以下代码实现了一个复制文件的操作。

        <?php
        $filename1 = "Test\\file.txt";
        $filename2 = "Test\\file.bak";
        copy($filename1, $filename2);                         //复制文件
        ?>

上面的代码运行后,文件file.txt将被复制到file.bak。

1.3 本地文件的操作实例——小型留言本

前面介绍了一些对文件的基本操作,对于一些小型并且对安全要求不高的项目来说,完全可以使用一个本地文本文件来存放数据。本节将要实现一个小型留言本的编写。这个留言本实现了两个最基本的功能,即留言和查看留言。

1.3.1 留言发表模块

留言发表模块提供给访问者的是一个简单的表单,用户在输入留言标题、留言内容和留言者姓名以后,程序会在文件夹DB下创建一个新的文本文件,并将用户输入的内容保存到这个文件中。

留言发表模块包括两个文件。Post.htm是一个静态的HTML页面,提供一个表单供用户输入。Post.php是一个PHP页面,用来接收用户的输入并将结果保存在文件夹DB中。

以下是Post.htm的HTML代码。

        <html>
        <head>
        <title>发表新的留言</title>
        <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
        </head>
        <body>
        <H1><p align="center">发表新的留言</p></H1>
        <form name="form1" method="post" action="Post.php">
          <table width="500" border="0" align="center" cellpadding="0" cellspacing="0">
            <tr>
              <td>标题</td>
              <td><input name="title" type="text" id="title" size="50"></td>
            </tr>
            <tr>
              <td>作者</td>
              <td><input name="author" type="text" id="author" size="20"></td>
            </tr>
            <tr>
              <td>内容</td>
              <td><textarea name="content" cols="50" rows="10" id="content"></textarea></td>
            </tr>
          </table>
          <p align="center">
            <input type="submit" value="Submit">
            <input type="reset" value="Reset">
        </p>
        </form>
        </body>
        </html>

该页面在浏览器中如图1-1所示。

图1-1 发表新留言界面

Post.php的代码如下所示。

        <?php
        $path = "DB/";                                                 //指定存储路径
        $filename = "S".date("YmdHis").".dat";                         //由当前时间产生文件名
        $fp = fopen($path.$filename, "w");                             //以写方式创建并打开文件
        fwrite($fp, $_POST["title"]."\n");                             //写入标题
        fwrite($fp, $_POST["author"]."\n");                            //写入作者
        fwrite($fp, $_POST["content"]."\n");                           //写入内容
        fclose($fp);                                                   //关闭文件
        echo "留言发表成功!";                                         //提示发表成功
        echo "<a href='Index.php'>返回首页</a>";
        ?>

上面的代码将在DB文件夹内创建一个以当前时间为文件名命名的文本文件,并且逐行写入标题、作者和内容。访问者在图1-1所示的表单中输入信息后,一个新的文件就会在DB文件夹中创建。需要注意的是在设计本例的文件名时的方法,为了避免文件名的冲突,采用当前系统时间作为文件名。

1.3.2 浏览模块

前面介绍了如何把用户的输入存放到文本文件中。本节中将要介绍的是将这些文件显示出来。代码如下所示。

        <?php
        $path = "DB/";                                             //定义路径
        $dr = opendir($path);                                      //打开目录
        while($filen = readdir($dr))                               //循环读取目录中的文件
        {
            //如果文件名不是当前目录或父目录则对该文件进行读取
            if($filen != "." and $filen != "..")
            {
                  $fs = fopen($path.$filen, "r");
                  echo "<B>标题:</B>".fgets($fs)."<BR>";
                  echo "<B>作者:</B>".fgets($fs)."<BR>";
                  echo "<B>内容:</B><PRE>".fread($fs, filesize($path.$filen))."</PRE>";
                  echo "<HR>";                                      //输入一条线用来隔开每条留言
                  fclose($fs);
            }
        }
        closedir($dr)                                              //关闭目录
        ?>

上面代码的运行结果如图1-2所示。上面的代码首先对文件夹DB进行读取并获得文件夹内的全部文件,针对每一个文件分别打开、读取并输出。每读取一个文件输出一条分隔线以标识该条留言的结束。

图1-2 浏览模块的输出结果

1.4 远程文件的操作实例

远程文件的操作与操作本地文件类似,只是将文件路径用网址代替。需要注意的是读取远程文件时一般仅使用读操作。PHP提供了一个配置参数来控制是否允许读取远程网址,该配置参数即php.ini文件中的allow_url_fopen选项,只要打开这个选项,就可以使用网址来代替文件名。

以下代码是一个简单的读取远程文件的例子,该实例获取了远程网址的前100个HTML字符。

        <?php
        $fp = fopen("http://127.0.0.1/test/test1.php", "r");       //打开文件
        echo fread($fp, 100);                                      //读取文件中的前100个字符
        fclose($fp);                                               //关闭文件
        ?>

可以看到,原来写在fopen的第一个参数中的文件路径在这里使用一个网址代替了。

1.5 文件的上传与下载

除了前面介绍的读取和写入文件的功能,在实际应用中还有一个经常用到的功能,就是文件的上传与下载。通过文件的上传与下载,可以实现访问者客户端与服务器的文件交换。

1.5.1 文件的上传

文件的上传与前面介绍的复制文件的方法类似。文件的上传通过函数move_uploaded_file来实现,语法格式如下。

        bool move_uploaded_file(string filename1, string filename2)

其中,filename1 是客户端源文件的文件名及其所在路径,filename2 是在服务器上的目标文件的文件名及其所在路径。源文件的地址可以从客户端获取,在表单上使用file控件即可。需要注意的是在文件上传时需要指明表单的属性为 enctype="multipart/form-data",这样就可以上传文件了。

以下代码是一个实现简单文件上传的例子。文件 Upload.htm 用来显示供用户输入的表单,文件Upload.php用来实现文件上传。

Upload.htm的HTML代码如下所示。

        <html>
        <head>
        <title>文件上传</title>
        <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
        </head>
        <H1>文件上传</H1>
        <form enctype="multipart/form-data" action="Upload.php" method="post">
            <input name="upfile" type="file"><BR>
            <input type="submit" value="Submit">
        </form>
        <body>
        </body>
        </html>

Upload.php的代码如下。

        <?php
        $uploadfile = "upfiles/".$_FILES['upfile']['name'];      //上传后文件所在的文件名和路径
        move_uploaded_file($_FILES['upfile']['tmp_name'], $uploadfile);   //上传文件
        print_r($_FILES);                                          //输出上传文件信息

?>

这里需要说明的是$_FILES。$_FILES 是一个全局变量二维数组。该数组中每一行由5个元素组成。主要包括以下几项。

➢ $_FILES[]['name']:客户端源文件名。

➢ $_FILES[]['type']:上传文件的类型。

➢ $_FILES[]['size']:上传文件的字节数。

➢ $_FILES[]['tmp_name']:文件上传后在服务器上的临时存储文件名。

➢ $_FILES[]['error']:文件上传的错误代码。如果为0则表示没有错误发生。

上述程序的运行结果如下。

        Array
        (
            [upfile] => Array
                (
                  [name] => simon.txt
                  [type] => text/plain
                  [tmp_name] => C:\php\tmp\phpA3.tmp
                  [error] => 0
                  [size] => 8
                )
        )

从上面输出的数组可以看出:上传的文件在客户端的文件名为 simon.txt;文件类型为text/plain,即文本型文件;上传后的临时存储路径为C:\php\tmp\phpA3.tmp;文件的大小为8字节;在文件上传过程中没有错误发生。

1.5.2 文件的下载

文件的下载与文件的读取方法基本相同,其基本原理是通过PHP代码读取文件然后将读取的内容输出到浏览器端。使用PHP程序进行文件下载的好处在于可以将文件的真实路径隐藏起来。然而,由于下载的文件的类型不同,在 PHP 程序中,需要使用 header 来定义文件的类型、大小等参数。以下代码实现了对downloads文件夹中的文件进行浏览和下载的功能。

        <?php
        $dir = "downloads/";                         //定义路径

        if(!isset($_GET['file']))                    //如果在参数中没有指定文件名,则读取文件列表
        {
            $dir_res = opendir($dir);                //打开目录
            echo "<H1>文件下载</H1>";
            while($filen=readdir($dir_res))          //循环读取目录中的文件
            {
                  if($filen != "." and $filen != "..")
                      echo "<a href='?file=".$filen."'>".$filen."</a><br>" ;
              }
              closedir($dir_res);                                       //关闭目录
        }
        else
        {
              $file_name = $dir . $_GET['file'];                        //获得当前文件名

              if ($fh = fopen($file_name, "r"))                         //打开文件
              {
                  $fsize = filesize($file_name);                        //获得文件大小
                  $path_parts = pathinfo($file_name);                   //获得文件路径信息
                  header("Content-type: application/octet-stream");     //定义文件类型
                  header("Content-Disposition: filename=\"" . $path_parts["basename"] . "\"");
                                                                        //定义文件名
                  header("Content-length: " . $fsize);                  //定义文件大小
                  while(!feof($fh))                                     //读取文件并输出
                  {
                      $buffer = fread($fh, 2048);
                      echo $buffer;
                  }
              }
        }
        ?>

代码运行结果如图1-3所示。

图1-3 文件下载页面

单击相应的文件链接,浏览器会将文件名作为参数传入程序并提示相应的下载对话框,如图1-4所示。

图1-4 文件下载对话框

1.6 小结

本章主要介绍了PHP中的文件操作。在实际应用中,对文件的操作是非常普遍的,掌握好操作文件的方法非常重要。对于文件的操作通常与对字符串的操作结合使用,下一章将主要介绍对字符串的操作方法。在实际应用中,经常结合文件的读写操作和字符串的处理方法实现需求中的功能。