--文件系统处理的作用
- PhP所有的项目都离不开文件处理。
- 可以用文件长时间保存数据。(这种情况不多,一般用数据库或xml保存数据)
- 建立缓存;服务器文件操作等。
--文件系统的组成:文件,目录。
--文件系统的操作分为文件的操作和目录的操作。这些操作都是使用系统函数完成的。是基于Linux/Unix系统的(大部分在Windows下没问题,有些可能有问题)
--文件的操作
- 获取文件类型
- 获取文件属性
- 和文件路径相关的函数处理
- 文件本身的操作(创建、删除、移动文件)
- 打开、关闭文件(读文件中的内容,向文件中写内容)
- 文件内部移动指针
- 文件锁定相关的一些机制
--目录的操作
- 目录的遍历
- 目录的创建
- 目录的删除
- 目录的复制
- 统计目录大小
--文件的上传和下载
=============================================================
--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 的信息。包括以下的数组单元:dirname,basename 和 extension。
--文件本身的操作(创建、删除、移动-重命名、复制文件)
- 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]] ) //向文件中写内容。如果文件存在,就覆盖原来的内容。如果文件不存在,就新建文件并写入内容。
参数返回值 该函数将返回写入到文件内数据的字节数。
按文件指针写(这种方式要求事先打开文件资源)
- int fwrite ( resource handle, string string [, int length] ) //把
string
的内容写入 文件指针handle
处。 如果指定了length
,当写入了length
个字节或者写完了string
以后,写入就会停止,视乎先碰到哪种情况。返回写入的字符数。
fwrite()的使用例子: (向文件中写内容,通常的处理流程是:先检查文件是否可写,再打开文件资源,检查是否写成功,关闭文件资源)
- <?php
- $filename = 'test.txt';
- $somecontent = "添加这些文字到文件\n";
- // 首先我们要确定文件存在并且可写。
- if (is_writable($filename)) {
- // 在这个例子里,我们将使用添加模式打开$filename,
- // 因此,文件指针将会在文件的开头,
- // 那就是当我们使用fwrite()的时候,$somecontent将要写入的地方。
- if (!$handle = fopen($filename, 'a')) {
- echo "不能打开文件 $filename";
- exit;
- }
- // 将$somecontent写入到我们打开的文件中。
- if (fwrite($handle, $somecontent) === FALSE) {
- echo "不能写入到文件 $filename";
- exit;
- }
- echo "成功地将 $somecontent 写入到文件$filename";
- fclose($handle);
- } else {
- echo "文件 $filename 不可写";
- }
- ?>
- fputs() 是fwrite()的别名。
--文件内部移动指针
- int ftell ( resource handle ) //返回由
handle
的文件指针的位置,也就是文件流中的偏移量。 - int fseek ( resource handle, int offset [, int whence] ) //在与
handle
关联的文件中设定文件指针位置。新位置从文件头开始以字节数度量,是以whence
指定的位置加上offset
。whence
的值定义为:- SEEK_SET - 设定位置等于
offset
字节。- SEEK_CUR - 设定位置为当前位置加上
offset
。 - SEEK_END - 设定位置为文件尾加上
offset
。(要移动到文件尾之前的位置,需要给offset
传递一个负值。)如果没有指定
whence
,默认为 SEEK_SET。成功则返回 0;否则返回 -1。注意移动到 EOF 之后的位置不算错误。
- SEEK_CUR - 设定位置为当前位置加上
- SEEK_SET - 设定位置等于
- 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(),比如
- $str = '';
- while(!feof($handle))
- {
- $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
指定的文件。
- bool is_uploaded_file ( string filename ) //如果
--文件下载的处理步骤
如果提供的下载文件是浏览器可以解释的内容的话,浏览器会直接打开,而不是下载,所以下载文件应采用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函数可以定义页面的字符集,比如
- header("Content-Type:text/html;charset=utf-8"); //定义页面的字符集为utf-8,浏览器接收到文件后将按照utf-8解释,不管实际是不是utf-8.
- header("location:two.html"); //浏览器接收后将会自动跳转到two.html文件
页面跳转实际用这种方式的不多,多采用JavaScript脚本来做页面跳转,比如
- echo '<script>window.location="http://www.daxiangwang.com"</script>';
- header函数可以定义页面的所有内容作为附件,比如
- header('Content-Disposition: p_w_upload; filename="downloaded.pdf"'); //页面的所有内容就被作为p_w_upload(附件)解释,p_w_upload的文件名为download.pdf
通常还配合header('Content-type: application/pdf'); 一起使用。
转载于:https://blog.51cto.com/stark/715079