--文件系统处理的作用

  • PhP所有的项目都离不开文件处理。
  • 可以用文件长时间保存数据。(这种情况不多,一般用数据库或xml保存数据)
  • 建立缓存;服务器文件操作等。

 

--文件系统的组成:文件,目录。

 

--文件系统的操作分为文件的操作和目录的操作。这些操作都是使用系统函数完成的。是基于Linux/Unix系统的(大部分在Windows下没问题,有些可能有问题)

--文件的操作

  1. 获取文件类型
  2. 获取文件属性
  3. 和文件路径相关的函数处理
  4. 文件本身的操作(创建、删除、移动文件)
  5. 打开、关闭文件(读文件中的内容,向文件中写内容)
  6. 文件内部移动指针
  7. 文件锁定相关的一些机制

 

--目录的操作

  1. 目录的遍历
  2. 目录的创建
  3. 目录的删除
  4. 目录的复制
  5. 统计目录大小

 

--文件的上传和下载

 =============================================================

--Linux文件的类型

  • block:块设备文件,包括磁盘分区、光驱、软驱等。
  • char:字符设备,比如i/o设备以字节为单位,如打印机、键盘。
  • dir:目录,在Linux下目录也当做是一种文件。
  • fifo:管道。
  • file:普通文件。
  • link:链接文件。
  • unknown:未知类型。

 

--获取文件类型

  • 在windows下只能获取file、dir、unknown 3种类型。(因为这些函数是以Linux为基础设计的)
  • 在linux下可以获取block,char,dir,fifo,file,link,unknown 7种类型。
  • string filetype ( string filename )

    返回文件的类型。可能的值有 fifo,char,dir,block,link,file 和 unknown。

    如果出错,返回False。

  • is_dir() //判断给定文件名是否是一个目录
  • is_file() //判断给定文件名是否为一个正常的文件
  • is_link() //判断给定文件名是否为一个符号连接
  • is_uploaded_file() //判断文件是否是通过 HTTP POST 上传的

 

--获取文件属性

  • file_exists(); //判断给定文件是否存在
  • filesize();    //获取文件大小
  • filectime();   //获取文件创建时间
  • filemtime();   //获取文件修改时间
  • fileactime();  //获取文件最后一次访问的时间
  • is_readable(); //判断给定文件名是否可读
  • is_writable();//判断给定的文件名是否可写
  • is_writeable();//判断给定的文件名是否可写,is_writable()的别名。
  • is_executable() //判断给定文件名是否可执行
  • stat();        //获取文件信息,返回一个数组

 

--路径分隔符

  • Linux/Unix 下用 "/"反斜杠
  • Windows下用     "\"正斜杠
  • php中有个常量DIRECTORY_SEPARATOR,表示分隔符,在不同系统会自动转为不同形式。

       比如$url ="windows".DIRECTORY_SEPARATOR."system".DIRECTORY_SEPARATOR."file.txt"

       在Windows下会转换为windows\system\file.txt;

       在Linux下会转换为windows/system/file.txt。

  • 实际上在程序中使用路径分隔符都可以用"/",因为php系统会自动将/转为操作系统支持的分隔符。(php,apache的配置文件也可以用"/"做路径分隔符)

       比如$url = "windows/system/file.txt"在windows下会转为windows\system\file.txt

 

--相对路径:以当前目录为参考的上一级或下一级目录。

  • .当前目录
  • ..上一级目录

 

--绝对路径:从根开始算的路径。

 关于根"/"的两种解释:

  • "/"指的是操作系统的跟。
  • "/"指的是存放网站的文档根目录

    具体指的是哪个,需要分情况考虑:

  • 在php服务器中(通过文件处理函数)使用的路径,指的是操作系统的根。
  • 在下载到客户端的代码中,(通过apache服务器)访问服务器的文件,指的是网站文档根目录。

    写网站的时候通常定义两种路径:绝对路径和应用路径。

  • 绝对路径指的是php程序执行的路径。
  • 应用路径指的是客户端程序所访问的路径。

 

 --和文件路径相关的函数处理

  • string basename ( string path [, string suffix] ) //给出一个包含有指向一个文件的全路径的字符串,本函数返回基本的文件名。如果文件名是以 suffix 结束的,那这一部分也会被去掉。
  •  string dirname ( string path ) //给出一个包含有指向一个文件的全路径的字符串,本函数返回去掉文件名后的目录名
  •  mixed pathinfo ( string path [, int options] ) //pathinfo() 返回一个关联数组包含有 path 的信息。包括以下的数组单元:dirnamebasenameextension

 

--文件本身的操作(创建、删除、移动-重命名、复制文件)

  • bool touch ( string filename [, int time [, int atime]] ) //创建操作,尝试将由 filename 给出的文件的访问和修改时间设定为给出的时间。如果没有给出可选参数 time,则使用当前系统时间。如果给出了第三个参数 atime,则给定文件的访问时间会被设为 atime。注意访问时间总是会被修改的,不论有几个参数。
  • bool unlink ( string filename ) //删除操作,删除 filename。和 Unix C 的 unlink() 函数相似。如果成功则返回 TRUE,失败则返回 FALSE
  • bool rename ( string oldname, string newname [, resource context] )

 //既是移动操作也是重命操作,尝试把 oldname 重命名为 newname。如果成功则返回 TRUE,失败则返回 FALSE

  • bool copy ( string source, string dest ) //复制操作,将文件从 source 拷贝到 dest。如果成功则返回 TRUE,失败则返回 FALSE

 

--和权限有关的函数

  • chgrp() //改变文件所属组
  • chmod() //改变文件模式
  • chown() //改变文件所有者
  • filegroup() //取得文件所属组
  • fileowner() //取得文件所有者

 

--本地文件和远程文件

  • 本地文件:可以用绝对路径和相对路径访问。比如"./text.php";"/usr/text.php"
  • 远程文件:比如http://www.baidu.com

 

--打开、关闭文件(读文件中的内容,向文件中写内容)

    从文件中读(本地、远程资源都可以读)

         读取全部文件,不能读取部分,也不能读取指定的区域。也不能加锁。

  • string file_get_contents ( string filename [, bool use_include_path [, resource context [, int offset [, int maxlen]]]] ) // 把文件读入一个字符串。将在参数 offset 所指定的位置开始读取长度为 maxlen 的内容。如果失败,file_get_contents() 将返回 FALSE。 将文件的内容读入到一个字符串中的首选方法.
  • int readfile ( string filename [, bool use_include_path [, resource context]] ) //读入一个文件并写入到输出缓冲。返回从文件中读入的字节数。如果出错返回 FALSE.

array file ( string filename [, int use_include_path [, resource context]] ) //和 file_get_contents() 一样,只除了 file() 将文件作为一个数组返回。数组中的每个单元都是文件中相应的一行,包括换行符在内。如果失败 file() 返回 FALSE。

    文件指针读(这种方式要求事先打开文件资源)

  • string fread ( int handle, int length ) //从文件指针 handle 读取最多 length 个字节
  • string fgetc ( resource handle ) //返回一个包含有一个字符的字符串。
  • string fgets ( int handle [, int length] ) //从 handle 指向的文件中读取一行并返回长度最多为 length - 1 字节的字符串。碰到换行符(包括在返回值中)、EOF 或者已经读取了 length - 1 字节后停止(看先碰到那一种情况)。如果没有指定 length,则默认为 1K,或者说 1024 字节。
     

 

 

 

  

 

     向文件中写(只有本地资源才可以写,远程资源只能读)

          写全部文件(这种方式是覆盖的,不能追加的):

  • int file_put_contents ( string filename, string data [, int flags [, resource context]] ) //向文件中写内容。如果文件存在,就覆盖原来的内容。如果文件不存在,就新建文件并写入内容。
        参数 
        filename:被写入数据的文件名。     data:写入的数据。类型可以是 stringarray 或者是 stream 资源(如  上面所说的那样)。     flags:可以是 FILE_USE_INCLUDE_PATH,FILE_APPEND 和/或 LOCK_EX(获得一个独占锁定),然而使用 FILE_USE_INCLUDE_PATH 时要特别谨慎。     context:一个 context 资源。
        返回值  该函数将返回写入到文件内数据的字节数。       

    

           文件指针写(这种方式要求事先打开文件资源)

  • int fwrite ( resource handle, string string [, int length] ) //把 string 的内容写入 文件指针 handle 处。 如果指定了 length,当写入了 length 个字节或者写完了 string 以后,写入就会停止,视乎先碰到哪种情况。返回写入的字符数。

     fwrite()的使用例子: (向文件中写内容,通常的处理流程是:先检查文件是否可写,再打开文件资源,检查是否写成功,关闭文件资源)      

 
  
  1. <?php 
  2. $filename = 'test.txt'
  3. $somecontent = "添加这些文字到文件\n"
  4.  
  5. // 首先我们要确定文件存在并且可写。 
  6. if (is_writable($filename)) { 
  7.  
  8.     // 在这个例子里,我们将使用添加模式打开$filename, 
  9.     // 因此,文件指针将会在文件的开头, 
  10.     // 那就是当我们使用fwrite()的时候,$somecontent将要写入的地方。 
  11.     if (!$handle = fopen($filename'a')) { 
  12.          echo "不能打开文件 $filename"
  13.          exit
  14.     } 
  15.  
  16.     // 将$somecontent写入到我们打开的文件中。 
  17.     if (fwrite($handle$somecontent) === FALSE) { 
  18.         echo "不能写入到文件 $filename"
  19.         exit
  20.     } 
  21.  
  22.     echo "成功地将 $somecontent 写入到文件$filename"
  23.  
  24.     fclose($handle); 
  25.  
  26. else { 
  27.     echo "文件 $filename 不可写"
  28. ?>  
  • fputs()  是fwrite()的别名。

 

 

--文件内部移动指针

  • int ftell ( resource handle ) //返回handle文件指针的位置,也就是文件流中的偏移量。
  • int fseek ( resource handle, int offset [, int whence] ) //在与 handle 关联的文件中设定文件指针位置。新位置从文件头开始以字节数度量,是以 whence 指定的位置加上 offsetwhence 的值定义为:
    • SEEK_SET - 设定位置等于 offset 字节。
      • SEEK_CUR - 设定位置为当前位置加上 offset
      • SEEK_END - 设定位置为文件尾加上 offset。(要移动到文件尾之前的位置,需要给 offset 传递一个负值。)     

        如果没有指定 whence,默认为 SEEK_SET

        成功则返回 0;否则返回 -1。注意移动到 EOF 之后的位置不算错误。

  • bool rewind ( resource handle ) //将 handle 的文件位置指针设为文件流的开头。如果成功则返回 TRUE,失败则返回 FALSE。 

 

--打开关闭文件

    打开文件

        resource fopen ( string filename, string mode [, bool use_include_path [, resource zcontext]] )

        将 filename 指定的名字资源绑定到一个流上。如果 filename 是 "scheme://..." 的格式,则被当成一个 URL,PHP 将搜索协议处理器(也被称为封装协议)来处理此模式。如果该协议尚未注册封装协议,PHP 将发出一条消息来帮助检查脚本中潜在的问题并将 filename 当成一个普通的文件名继续执行下去。

        如果 PHP 认为 filename 指定的是一个本地文件,将尝试在该文件上打开一个流。该文件必须是 PHP 可以访问的,因此需要确认文件访问权限允许该访问。

        模式:

  •         'r':只读的方式打开,将文件指针指向文件头
  •         'r+':读写的方式打开,文件指针指向文件头。如果文件不存在,就会报错。
  •         'w':写入方式打开,将文件指针指向文件头并将文件大小为零。如果文件不存在则尝试创建之。(覆盖的方式
  •         'w+':读写方式打开,将文件指针指向文件头并将文件大小为零。如果文件不存在则尝试创建之。
  •         'a':写入方式打开,将文件指针指向文件末尾。如果文件不存在则尝试创建之。如果文件存在,并且有内容,不清除文件原有内容,在原有内容的最后,写入新内容。(追加的方式
  •         'a+':读写方式打开,将文件指针指向文件末尾。如果文件不存在则尝试创建之。如果文件存在,并且有内容,不清除文件原有内容,在原有内容的最后,写入新内容。
  •         'b':以2进制模式打开文件。(windows下有2进制模式和文本,两个模式,所以打开图片视频的时候需要用到这个模式,通常配合其他模式选项,比如‘rb’或'wb';linux下只有2进制模式,所以不用加'b' )

 

     关闭文件

           bool fclose ( resource handle ) //关闭一个文件资源。

           使用完一个资源就要释放掉,如果不这样的话,该资源会一直占用内存,直到脚本执行结束。

 

      测试文件结束

           bool feof ( resource handle ) //如果文件指针到了 EOF(文件结尾) 或者出错时则返回 TRUE,否则返回一个错误(包括 socket 超时),其它情况则返回 FALSE

  

--读文件技巧

  • 读本地文件的方法:可以用fread($handle,filesize($filename)),文件大小可以用filesize($filename)确定。
  • 读远程文件的方法:因为远程文件无法确定大小(filesize()只能用在本地文件),所以要用while循环配合feof(),比如 
 
  
  1. $str = ''
  2. while(!feof($handle)) 
  3.     $str .= fread($handle,1024); //文件都暂时缓存到$str中,每次读1024个字节,直到文件末尾

--文件的锁定机制

bool flock ( resource handle, int operation [, int &wouldblock] )

 

     PHP 支持以咨询方式(也就是说所有访问程序必须使用同一方式锁定, 否则它不会工作)锁定整个文件的一种轻便方法。

注意: 在 Windows 下 flock() 将会强制执行。

        flock() 操作的 handle 必须是一个已经打开的文件指针。operation 可以是以下值之一:

 

  • 要取得共享锁定(读取的程序),将 operation 设为 LOCK_SH(PHP 4.0.1 以前的版本设置为 1)。为什么读文件也要加锁?因为读文件加锁,可以防止在读的时候,别的程序写该文件;也可以防止读到正在写的文件(设共享锁定之前,php会先检查是否该文件之前已经被独占锁定)

  • 要取得独占锁定(写入的程序),将 operation 设为 LOCK_EX(PHP 4.0.1 以前的版本中设置为 2)。

  • 要释放锁定(无论共享或独占),将 operation 设为 LOCK_UN(PHP 4.0.1 以前的版本中设置为 3)。

  • 如果不希望 flock() 在锁定时堵塞,则给 operation 加上 LOCK_NB(PHP 4.0.1 以前的版本中设置为 4)。

    锁定操作也可以被 fclose() 释放(代码执行完毕时也会自动调用)。

     如果锁定成功则返回 TRUE,失败则返回 FALSE

关于锁定的深层讨论,参见http://stark.blog.51cto.com/189176/730553

 

--目录的遍历

     遍历,计算目录大小都需要自己去写,需要用到的函数有:

  • resource opendir ( string path [, resource context] ) //如果成功则返回目录句柄resource,失败则返回 FALSE。目录句柄可用于之后的 closedir()readdir()rewinddir() 调用中。
  • string readdir ( resource dir_handle ) //返回目录中下一个文件的文件(文件名可以是文件的名,也可以是目录的名)。文件名以在文件系统中的排序返回。每次读取后目录指针向后面移动一位,当读取到最后一个文件返回false。流必须之前被 opendir() 所打开。
  • void rewinddir ( resource dir_handle ) //将 dir_handle 指定的目录流重置到目录的开头。流必须之前被 opendir() 所打开。
  • void closedir ( resource dir_handle ) //关闭dir_handle 指定的目录流。流必须之前被 opendir() 所打开。

 

--创建、删除目录

bool mkdir ( string pathname [, int mode [, bool recursive [, resource context]]] ) //尝试新建一个由 pathname 指定的目录(创建一个空目录)。如果成功则返回 TRUE,失败则返回 FALSE
bool rmdir ( string dirname ) //尝试删除 dirname 所指定的目录。 该目录必须是的,而且要有相应的权限。如果成功则返回 TRUE,失败则返回 FALSE

 

--重命名、移动目录

和文件一样,重命名、移动目录都是rename()函数。目录可以不为空。

 

--复制目录

需要自己写。

 

--php配置文件中和文件上传有关的选项

  • file_uploads = on //打开上传功能
  • upload_max_filesize = 若干M //超过服务器内存
  • upload_tmp_dir = 某目录 //上传文件的临时目录,如果不设定这个选项,将默认使用操作系统的临时目录。
  • post_max_size = 若干M //使用post传数据时的最大值,包含上传的文件以及表单内容,所以大于upload_max_filesize

 

--编写上传表单的注意事项

  • 如果有文件上传,form标签的method属性必须为"post"。
  • 如果有文件上传,form标签的enctype属性必须为"multipart/form-data"(在使用包含文件上传控件的表单时,必须使用该值),表示不对字符编码,并且让服务器知道我们要传递一个文件。(该值默认为text/plain,空格转换为 "+" 加号,但不对特殊字符编码)
  • 如果有文件上传,input标签的type属性要有取值为"file"的。
  • 建议添加一个隐藏标签(type为hidden,name为MAX_FILE_SIZE),用于提示用户上传的最大文件限制(只是提示作用,并不能实际起到限制作用,单位为字节)。

 

--PHP处理上传的文件

  • 用$_POST数组接收非文件数据。
  • 用$_FILES数组接收文件。

 

--文件上传的处理步骤($_FILE数组的详细介绍,参见:http://stark.blog.51cto.com/189176/742540

  • 检查错误:使用$_FILE[关于文件的表单名]["error"]做出错处理
  • 检查文件大小:使用$_FILE[关于文件的表单名]["size"]检查文件大小,是否符合要求。
  • 检查文件类型:使用$_FILE[关于文件的表单名]["type"](这是一种MIME类型http://stark.blog.51cto.com/189176/735475)或文件扩展名,检查文件类型是否符合要求。
  • 将上传的文件移动、改名,用到的函数有:
    • bool is_uploaded_file ( string filename ) //如果 filename 所给出的文件是通过 HTTP POST 上传的则返回 TRUE。这可以用来确保恶意的用户无法欺骗脚本去访问本不能访问的文件,例如 /etc/passwd
    • bool move_uploaded_file ( string filename, string destination ) //本函数检查并确保由 filename 指定的文件是合法的上传文件(即通过 PHP 的 HTTP POST 上传机制所上传的)。如果文件合法,则将其移动为由 destination 指定的文件

 

--文件下载的处理步骤

如果提供的下载文件是浏览器可以解释的内容的话,浏览器会直接打开,而不是下载,所以下载文件应采用a标签中连接php文件,php文件中包含header函数,header函数中说明了下面读到的内容是附件,php文件中读取提供下载的文件。具体步骤:

  • 网页的a标签中引用down.php
  • down.php中使用header函数,header函数定义了下面的内容为附件;
  • down.php用readfiele()读取提供下载的文件

 

--http请求数据的组成(3部分)

  • 协议和版本,比如"HTTP 1.1";
  • 头信息(包含客户端的浏览器,操作系统等信息);
  • 表单信息(这里才是用户提交的数据),比如http://www.baidu.com?aa=aaa&bb=bbb

 

--http响应数据的组成

  • 状态,比如200 ok,404页面没找到。
  • 头信息(包含:是哪种类型的数据,比如文本还是图片,用mime类型表示;如果文本的话还告诉了是哪种字符集;web服务器是什么,比如apache;脚本处理器是什么,比如php),告诉客户端如何处理数据。
  • 发送给用户的数据

 

--更改响应包头信息的函数

header(),header函数必须放在php的所有输出之前,否则会报错。

  • header函数可以定义页面的字符集,比如
 
  
  1. header("Content-Type:text/html;charset=utf-8"); //定义页面的字符集为utf-8,浏览器接收到文件后将按照utf-8解释,不管实际是不是utf-8.
header函数可以 定义位置,比如
 
  
  1. header("location:two.html"); //浏览器接收后将会自动跳转到two.html文件 

     页面跳转实际用这种方式的不多,多采用JavaScript脚本来做页面跳转,比如

 
  
  1. echo '<script>window.location="http://www.daxiangwang.com"</script>'
  •  header函数可以定义页面的所有内容作为附件,比如
 
  
  1. header('Content-Disposition: p_w_upload; filename="downloaded.pdf"'); //页面的所有内容就被作为p_w_upload(附件)解释,p_w_upload的文件名为download.pdf 

    通常还配合header('Content-type: application/pdf'); 一起使用。