PHP如何操作目录与文件?

一、文件目录操作

文件目录是指存储在磁盘中的文件的索引,也可以将其视为一个文件夹,在这个文件夹中可以存放其他文件或文件夹。最顶层的目录是磁盘的根目录,用“/”或“\\”表示。“/”表示当前工作目录,“../”表示Apache的文件根目录。文件夹前不指定位置,则默认在当前工作目录中查找。

1.创建和删除目录

使用mkdir()函数可以根据提供的目录名或目录的全路径,创建新的目录,成功则返回TRUE,否则返回FALSE。

使用rmdir()函数可以删除一个空目录,但必须具有相应的权限,如果目录不为空,必须先删除目录中的文件才能删除目录。删除成功则返回TRUE,否则返回FALSE。

2.获取和更改当前工作目录

当前工作目录是指正在运行的文件所处的目录,使用getcwd()函数可以取得当前的工作目录,该函数没有参数,成功则返回当前的工作目录,失败则返回FALSE。

使用chdir()函数可以设置当前的工作目录,该函数的参数是新的当前目录。

“@”错误控制运算符可以用于抑制错误信息。

3.打开和关闭目录句柄

文件和目录的访问都是通过句柄实现的,使用opendir()函数可以打开一个目录句柄,该函数的参数是打开的目录路径,打开成功则返回TRUE,失败则返回FALSE,打开句柄后其他函数就可以调用该句柄。为了节省服务器资源,使用完一个已经打开的目录句柄后,应该用closedir()函数关闭这个句柄。

4.读取目录内容

readdir()函数读取目录内容,该函数参数是一个已经打开的句柄目录。该函数在每次调用时返回目录中下一个文件的文件名,在列出了所有的文件名后,函数返回FALSE。该函数结合while循环可以实现对目录的遍历。

PHP是弱类型语言,所以将整数值0和布尔值FALSE视为等价,如果使用比较运算符“==”或“!=”,当遇到目录中有一个文件的文件名为“0”时,则遍历目录的循环将停止。所以在设置判断条件时要使用“===”和“!==”运算符进行强类型检查。

5.获取指定路径的目录和文件

scandir()函数列出指定路径中的目录和文件。

array scandir(string $directory[,int $sorting_order[,resource $context]])

$directory为指定路径。参数$sorting_order默认是按字母升序排列,如果设为1表示按字母的降序排列。$context是可选参数,是一个资源变量,可以用stream_context_create()函数生成,这个变量保存着与具体的操作对象有关的一些数据。函数运行成功则返回一个包含指定路径下的所有目录和文件名的数组,失败则返回FALSE。

二、操作文件的一般方法

操作文件的一般方法有打开、读取、写入、关闭等。

如果要将数据写入一个文件,一般先要打开该文件,如果文件不存在则先创建它,然后将数据写入文件,最后还需要关闭这个文件。

如果要读取一个文件中的数据,同样要先打开该文件,如果文件不存在则自动退出,如果文件存在则读取该文件的数据,读完数据后关闭文件。

无论如何,如果想对文件操作,都要先打开文件,使用完文件后需要关闭文件。

1.文件的打开与关闭

打开文件使用fopen()函数。

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

Ⅰ$filename参数。fopen()函数将$filename参数指定的名字资源绑定到一个流上。

如果$filename的值是一个由目录和文件名组成的字符串,则PHP认为指定的是一个本地文件,将尝试在该文件上打开一个流。如果文件存在,函数将返回一个句柄,如果文件不存在或没有该文件的访问权限,则返回FALSE。

如果$filename是“scheme://...”格式,则被当作一个URL,PHP将搜索协议处理器来处理此模式。如果访问的文件不存在或没有访问权限,函数返回FALSE。

访问本地文件时,在UNIX环境下,目录中的间隔符为正斜线“/”在Windows环境下可以是正斜线“/”或双反斜线“\\”。另外要访问URL形式的文件时,首先要确定PHP配置文件中的allow_url_fopen选项处于打开状态,如果处于关闭状态,PHP将发出一个警告,而fopen()函数则调用失败。

Ⅱ$mode参数指定了fopen()函数访问文件的模式

$mode说明
'r'只读方式打开文件,从文件头开始读
'r+'读写方式打开文件,从文件头开始读写
'w'写入方式打开文件,将文件指针指向文件头,如果文件已经存在则删除已有内容,如果文件不存在则尝试创建它
'w+'读写方式打开文件,将文件指针指向文件头,如果文件已经存在则删除已有内容,如果文件不存在则尝试创建它
'a'写入方式打开文件,将文件指针指向文件末尾,如果文件已有内容将从文件末尾开始写。如果文件不存在则尝试创建它
'a+'读写方式打开文件,将文件指针指向文件末尾,如果文件已有内容将从文件末尾开始读写,如果文件不存在则尝试创建它
'x'创建并以写入方式打开文件,将文件指针指向文件头。如果文件已存在,则fopen()调用失败并返回FALSE,并生成一条E_WARNING级别的错误信息。如果文件不存在则尝试创建它
'x+'创建并以读写方式打开文件,将文件指针指向文件头,如果文件已存在,则fopen()调用失败并返回FALSE,并生成一条E_WARNING级别的错误信息。如果文件不存在则尝试创建它
'b'二进制模式,用于连接在其他模式后面。如果文件系统能够区分二进制文件和文本文件,需要使用到这个选项。

如果需要打开本地的二进制文件,操作与打开本地文件基本相同,主要区别在于操作二进制文件时,应在$mode取值的后面加上标记"b"作为最后一个字符,在操作二进制文件时,不使用此标记可能会损坏文件。

Ⅲ$user_include_path参数。如果需要在include_path中搜寻文件,可以将可选参数$user_include_path的值设为1或TRUE,默认为FALSE

Ⅳ$context参数,可选的$context参数只有文件被远程打开时才能使用,它是一个资源变量,其中保存着与fopen()函数具体的操作对象有关的一些数据。如果fopen()打开的是一个HTTP地址,那么这个变量记录着HTTP请求的请求类型、HTTP版本及其他头信息,如果打开的是FTP地址,记录的可能是FTP的被动/主动模式。

2.关闭文件

使用fclose()函数关闭文件

bool fclose(resource $handle)

参数$handle为要打开的文件指针,文件指针必须有效,如果关闭成功则返回TRUE,否则返回FALSE。

三、文件的写入

PHP中没有专门用于创建文件的函数,一般可以使用fopen()函数来创建,文件模式可以是"w"、"w+"、"a"、"a+"。

Ⅰ fwrite()函数,文件打开后,向文件中写入内容可以使用fwrite()函数。

int fwrite(resource $handle,string $string[,int $length])

参数$handle是写入的文件句柄,$string是将要写入文件的字符串数据,$length是可选参数,如果指定了$length,则当写入了$string中的前$length个字符的数据后停止写入。如果字符串$string中的字节数小于$length,则写入整个字符串后就停止写入。如果写入操作成功,fwrite()函数将返回写入的字节数,出现错误时返回FALSE。

fwrite()函数还有一个别名fputs(),fwrite()函数还可用于写入二进制文件。

如果以写入方式“w”打开文件,写入的新数据将覆盖旧数据,如果不想覆盖之前的数据而将新数据添加到文件末尾,可以使用追加模式"a"来打开文件。

Ⅱ file_put_contents()函数

int file_put_contents(string $filename,string $data[,int $flags[,resource $context]])

$filename是要写入数据的文件名,$data是要写入的字符串,$data也可以是数组,但不能为多维数组。在使用FTP或HTTP向远程文件写入数据时,可以使用可选参数$flags和$context。写入成功后汉书返回写入的字节数,否则返回FALSE。

Ⅲ fputcsv()函数。CSV是一种比较常见的文件格式,一般以.csv作为扩展名。CSV格式把文件的一行看作是一条记录,记录里的字段使用逗号分隔。在PHP中使用fputcsv()函数可以把制定的数组格式化为符合CSV文件格式的内容,并写入文件指针指向的当前行。

int fputcsv(resource $handle[,array $fileds[,string $delimiter[,string $enclosure]]])

参数$handle是要写入的文件句柄,参数$fileds是要格式化的数组。可选$delimiter参数用于设定字段分界符(只允许一个字符),默认为逗号。可选的$enclosure参数设定字段环绕符(只允许一个字符),默认为双引号。

四、文件的读取

1.读取任意长度

fread()函数可以用于读取文件的内容

string fread(int $handle,int $length)

参数$handle是已经打开的文件指针,$length是指定读取的最大字节数,$length的最大取值为8192。如果读完$length个字节数之前遇到文件结尾标志(E0F),则返回所读取的字符,并停止读取操作。如果读取成功则返回所读取的字符串,如果出错返回FALSE。

feof()函数用于判断是否到达文件末尾,feof()函数只有一个参数,就是文件句柄,如果文件指针到达文件末尾,则feof()函数返回TRUE,否则返回FALSE。

filesize()函数的作用是取得文件内容的字节数

2.读取整个文件

Ⅰ file()函数用于将整个文件读取到一个数组中

array file(string $filename[,int $use_include_path[,resource $context]])

本函数的作用是将文件作为一个数组返回,数组中的每个单元都是文件中相应的一行,包括换行符在内。如果失败则返回FALSE。参数$filename是读取的文件名。

file()函数不适合操作很大的文件,如果文件过大,加载到数组中,数组需要的内存可能会超过可用内存。

Ⅱ readfile()函数。readfile()函数用于输出一个文件的内容到浏览器中,语法格式如下:

int readfile(string $filename[,bool $use_include_path[,resource $context]])

该函数打开一个文件,读取该文件并写入到输出缓冲,并返回从文件中读入的字节数。如果出错则返回FALSE,最后关闭这个文件。

Ⅲ fpassthru()函数可以将给定的文件指针从当前位置读取到EOF,并把结果写到输出缓冲区,要使用这个函数,必须先使用fopen()函数打开文件,然后将文件指针作为参数传递给fpassthru()函数,fpassthru()函数把文件指针所指向的文件内容发送到标准输出,如果操作成功返回读取到的字节数,否则返回FALSE。

如果既不修改文件也不在特定位置检索,只想将文件的内容下载到输出缓冲区,应该使用readfile()函数。

Ⅳ file_get_contents()函数可以将整个或部分文件内容读取到一个字符串中

string file_get_contents(string $filename[,int $offset[,int $maxlen]])

$filename是要读取的文件名,可选参数$offset可以指定从文件头开始的偏移量,函数可以返回从$offset所指定的位置开始长度为$maxlen的内容,如果失败,函数将返回FALSE。

file_get_contents()函数是用来将文件的内容读入到一个字符串中的首选方法。

3.读取一行数据

Ⅰ fgets()函数可以从文件中读取一行文本

string fgets(int $handle[,int $length])

$handle是已经打开的文件句柄,可选参数$length指定了返回的最大字节数,考虑到行结束符,最多可以返回$length-1个字节的字符串,如果没有制定$length,默认为1024个字节。

Ⅱ fgetss()函数是从文件指针处读取一行数据,不过fgetss()函数会尝试从读取的文本中去掉任何HTML和PHP标记。

string fgetss(resource $handle[,int $length[,string $allowable_tags]])

可选的第三个参数$allowable_tags用于指定哪些标记不被去掉。

Ⅲ fgetcsv()函数可以读取指定文件的当前行,使用CSV格式解析出字段,并返回一个包含这些字段的数组。

array fgetcsv(int $handle[,int $length[,string $delimiter[,string $enclosure]]])

$handle是打开的文件句柄,$length指定获取的字符的最大长度。可选的$delimiter参数用于设定字段分界符(只允许一个字符),默认为逗号,可选的$enclosure参数设定字段环绕符(只允许一个字符),默认为双引号。

4.读取一个字符

Ⅰ fgetc()函数可以从文件指针处读取一个字符。

string fgetc(resource $handle)

该函数返回$handle指针指向的文件中的一个字符,遇到EOF则返回FALSE。

5.使用指定格式读取文件

fscanf()函数可以读取文件中的数据,并根据制定的格式进行格式化,并返回一个数组。

mixed fscanf(resource $handle,string $format[,mixed &$...])

fscanf()函数从与$handle关联的文件中接收输入并根据指定的$format来解释输入。如果只给此函数传递了这两个参数,解析后的值会被作为数组返回,否则如果提供了可选参数,此函数将返回被复制的数目,可选参数必须用引用传递。

格式字符串中的任何空白会与输入流中的任何空白匹配,这意味着甚至格式字符串中的制表符"\t"也会与输入流中的一个空格字符串匹配。

五、文件的上传与下载

在PHP中实现文件的上传与下载,都需要使用文件系统函数来完成。处理上传文件的函数是move_uploaded_file(),实现文件下载可以使用header()和readfile()函数来完成。

1.文件上传

上传文件可以通过提交HTML表单来实现。

$_FILES是一个二维数组,上传后的文件信息可以使用以下形式获取:

Ⅰ $FILES['file']['name']。客户端上传的原文件名。其中“file”是HTML表单中文件域控件的名称。

Ⅱ $FILES['file']['type']。文件上传的类型,需要浏览器提供该信息的支持。常用的值有“text/plain”表示普通文本文件,“p_w_picpath/gif”表示GIF图片,“p_w_picpath/pjpeg”表示JPEG图片,“application/msword”表示word文件,“text/html”表示html格式的文件,“application/pdf”表示PDF格式文件,“audio/mpeg”表示MP3格式的音频文件,“application/x-zip-compressed”表示zip格式的压缩文件,“application/octet-stream”表示二进制流文件。

Ⅲ $FILES['file']['tmp_name'],文件被上传后再服务器端存储的临时文件名

Ⅳ $FILES['file']['size'].已上传文件的大小,单位为字节

Ⅴ $FILES['file']['errot'],错误信息代码,值为0表示没有错误发生,文件上传成功。值为1表示上传的文件超过了php.ini文件中的upload_max_filesize选项限制的值。值为2表示上传文件的大小超过了HTML表单中规定的最大值。值为3表示文件只有部分被上传,值为4表示没有文件被上传,值为5表示上传文件大小为0.

文件上传结束后,默认地存储在临时目录中,这时必须将其从临时目录中删除或移动到其他地方,不管是否上传成功,脚本执行完后临时目录里的文件肯定会被删除,所以在删除之前要使用PHP的move_uploaded_file()函数将它移动到其他位置,此时,才完成了上传文件过程。move_uploaded_file()函数的语法格式:

bool move_uploaded_file(string $filename,string $destination)

$filename参数是上传的文件名,如果$filename指定的是合法的文件,则函数会将文件移动至有$destination参数指定的文件。如果目标文件已经存在,会被新文件覆盖。如果上传文件不合法或文件无法移动,函数则不会进行任何操作并返回FALSE。

在将文件移动之前需要检查文件是否是通过HTTP POST上传的,这可以用来确保恶意的用户无法欺骗脚本去访问本不能访问的文件,这需要使用is_uploaded_file()函数。该函数的参数为文件的临时文件名,若文件是通过HTTP POST上传的,则函数返回TRUE。

要使HTML表单产生文件上传变量必须满足3个条件:表单必须使用POST方法提交;<form>标记enctype属性规定了在提交表单时要使用那种内容类型,在表单需要二进制数据时,比如文件内容,必须使用enctype值为“multipart/form-data”;表单中要包含一个文件域控件。

2.文件下载

如果是普通的文件下载,建立一个超链接指向目标文件就可以了。要实现安全的文件下载,在PHP中一般使用header()的readfile()函数来完成。

header()函数的作用是向浏览器发送正确的HTTP报头,报头指定了网页内容的类型、页面的属性等信息。header()函数的功能很多,举例如下:

Ⅰ 页面跳转。如果header()函数的参数为“Location:xxx”,页面就会自动跳转到“xxx”指向的URL地址。

Ⅱ 指定页面内容。例如,同样一个XML格式的文件,如果header()函数的参数指定为“Content-type:application/xml”,浏览器会将其按照XML文件格式来解析。但如果是“Content-type:text/xml”,浏览器就会将其看作文本解析。

Ⅲ 文件下载。header()函数结合readfile()函数可以下载将要浏览的文件。

注意:如果服务器的输出缓存没有开启,在调用header()函数之前如果输出了内容,如普通的HTML标记、空格、PHP输出等,在调用header()函数就会出错。开启输出缓存之后,输出的内容在执行过程中被放进缓存里,在调用header()函数就不会出错。开启输出缓存的方法是修改PHP配置文件php.ini文件中“output_buffering”选项的值。在旧的PHP版本中,“output_buffering”选项的默认值为Off,表示关闭缓存,需要修改为On或大于0的整数。

六、其他常用文件函数

1.计算文件大小

使用filesize()函数计算文件的大小,以字节为单位。

filesize()函数结合fread()函数可以实现一次读取整个文件(或某部分)。

fileatime()函数用于取得文件的上次访问时间,fileowner()函数用于取得文件的所有者,filetype()函数用于取得文件的类型。

2.判断文件是否存在

如果希望在不打开文件的情况下检查文件是否存在,可以使用file_exists()函数。函数的参数为指定的文件或目录,如果该文件或目录存在,则返回TRUE,否则返回FALSE。

is_dir()函数用于判断给定文件名是否是目录,is_file()函数用于判断给定文件名是否是文件,is_readable()函数用于判断给定文件名是否可读,is_writeable()函数用于判断给定文件是否可写。

3.删除文件

使用unlink()函数可以删除不需要的文件,成功即返回TRUE,否则返回FALSE。

4.复制文件

使用copy()函数可以完成复制一个文件或目录到某个文件夹的情况。语法格式如下;

bool copy(string $source,string $dest)

参数$source为需要复制的源文件,参数$dest为目标文件。复制后的新文件中内容与源文件完全相同,并且在复制文件的同时,也可以为新文件重新命名。复制成功即返回TRUE,否则返回FALSE。如果目标文件已经存在,则将被覆盖。

5.移动、重命名文件

出来move_uploaded_file()函数,还有一个rename()函数也可以移动文件。

bool rename(string $oldname,string $newname[,resource $context])

rename()函数主要用于对一个文件进行重命名,$oldname是文件的旧名,$oldname为新的文件名。如果$oldname与$newname的路径不相同,就实现了移动该文件的功能。

6.文件指针操作

PHP中有很多操作文件指针的函数,如rewind()、ftell()、fseek()函数等。feof()函数用于测试文件指针是否处于文件尾部,也属于文件指针操作函数。

Ⅰ rewind()函数用于重置文件的指针位置,使指针返回到文件头。它的参数只有一个,就是已经打开的指针文件的文件句柄。

Ⅱ ftell()函数。可以以字节为单位,报告文件中指针的位置,也就是文件流中的偏移量。它的参数也是已经打开的文件句柄。

Ⅲ fseek()函数。可以用于移动文件指针,语法格式如下:

int fseek(resource $handle,int $offset[,int $whence])

说明:fseek()函数可以将文件指针$handle,从$whence位置移动$offset个字节。新位置从文件头开始以字节数度量,以$whence指定的位置加上$offset。可选参数$whence的值可以是:SEEK_SET(文件开始处)、SEEK_CUR(文件指针的当前位置)和SEEK_END(文件末尾)。如果没有指定$whence,默认为SEEK_SET,要移动到文件末尾的位置,需要$offset传递一个负值。函数如果操作成功则返回0,否则返回-1.注意,移动到EOF之后的位置不算错误。