第十三章:文件系统
1:文件处理——文件处理包括:读取、关闭、重写等。访问一个文件需要3步:打开文件、读写文件、关闭文件。其他操作要么是包含在读写文件中(如显示内容、写入内容等),要么与文件自身的属性有关系(如文件遍历、文件改名等)
1.1:打开/关闭文件——使用fopen()函数和fclose()函数。打开文件应格外认真,因为不小心就可能将文件内容全部删除掉
1)打开文件
resource fopen (string filename, string mode [,bool use_include_path]);
filename是要打开的包含路径的文件名,可以是相对路径,也可以是绝对路径。如果没有任何前缀责表示打开的是本地文件;mode是打开文件的方式;use_include_path是可选参数,在php.ini中指定一个路径,如 F:\Appserv\www\mess.php,如果希望服务器在这个路径下打开所指定的文件,可设置为1或true
2)关闭文件——对文件的操作结束后应该关闭这个文件,否则可能引起错误: bool fclose( resource handle )
该函数将参数handle指向的文件关闭,如果成功,返回true,否则返回false。其中文件指针必须是有效的。如:
$f_open = fopen("../file.txt", "rb"); ... fclose($f_open);
1.2:读写文件
1)从文件中读取数据——从文件中读取数据,可以读取一个字符、一行字串或整个文件,还可以读取任意长度的字串
A:读取整个文件:readfile()、 file() 和 file_get_contents()
a:readfile()函数——用于读入一个文件并将其写入到输出缓冲,如果出现错误则返回false。语法如下:
int readfile(string filename)
使用readfile()函数,不需要打开/关闭文件,不需要echo/print 等输出语句,直接写出文件路径即可
b:file() 函数——也可以读取整个文件的内容,只是file() 函数将文件内容按行存放到数组中,包括换行符在内,失败返回false。语法如下:
array file(string filename)
c:file_get_contents()函数——该函数将文件内容(filename)读入一个字符串。如果有offset和maxlen 参数,将在参数 offset 所指定的位置开始读取长度为maxlen的内容,失败返回false。语法如下:
string file_get_contents(string filename [, int offset [,int maxlen]])
该函数适用二进制对象,是将整个文件的内容读入到一个字符串中的首选方式。
//使用readfile()函数读取tm.txt文件的容 <?php readfile('tm.txt'); ?> //使用file()函数读取tm.txt文件的内容 $f_arr = file("tm.txt"); foreach ($f_arr as $cont){ echo $cont."<br>"; } //使用file_get_contents()函数读取 $f_chr = file_get_contents("tm.txt"); echo $f_chr;
B:读取一行数据: fgets() 和 fgetss()
a:fgets()函数——用于一次读取一行数据。语法如下:
string fgets( int handle [, int length] )
参数 handle 是被打开的文件,参数length 是要读取的数据长度。函数能够实现从handle 指定文件中读取一行并返回长度最大值为length-1 个字节的字符串。
在遇到换行符、EOF 或者读取了 length-1 个字节后停止。如果没有length,那么读取数据直到行结束
b:fgetss()函数——是fgets()的变体,用于读取一行数据,同时,fgetss() 函数会过滤掉被读取内容中的html和php标记。语法如下:
string fgetss( resource handle [, int length [, string allowable_tags]] )
可以使用allowable_tags 参数来控制哪些标记不被过滤掉
// 使用 fgets 函数读取php文件 $fopen = fopen('test.php', 'rb'); // feof()函数测试指针是否到了文件结束的位置 while (!feof($fopen)){ echo fgets($fopen); // 输出当前行 } fclose($fopen); //使用 fgetss 函数读取php文件 $open = fopen('test.php', 'rb'); while(!feof($open)){ echo fgetss($fopen); } fclose($fopen);
C:读取一个字符:fgetc()函数 —— 在对某一个字符进行查找、替换时,需要有针对性的对某个字符进行读取,在PHP中可以使用此函数。语法:
string fgetc( resource handle )
该函数返回一个字符,该字符从handle指向的文件中得到。遇到 EOF 则返回 false
$fopen = fopen('03.txt', 'rb'); //创建文件资源 //使用 fgetc() 函数取得一个字符,判断是否为false while ( false !== ($chr = fgetc ($open) )){ echo $chr; } fclose($fopen);
D:读取任意长度的字串 —— fread() 函数,可以从文件中读取指定长度的数据
string fread ( int handle, int length )
参数 handle 为指向的文件资源,length 是要读取的字节数。当函数读取 length 个字节 或到达 EOF 时停止执行
$filename = "04.txt"; // 要读取的文件 $fp = fopen($filename, "rb") // 打开文件 echo fread($fp, 32); // 读取文件内容的前32个字节 echo "<p>"; echo fread($fp, filesize($filename) ); //输出其余的文件的内容
2)将数据写入文件—— 使用 fwrite() 和 file_put_contents() 函数向文件中写入数据。 fwrite() 函数也称 fputs(),他们用法相同:
int fwrite ( resource handle, string string [, int length] )
该函数把内容string 写入文件指针 handle 处。length:写入 length 个字节。如果文件内容长度小于length,则会输出全部文件内容
file_put_contents() 函数是php5 新增:
int file_put_contents( string filename, string data [, int flags] )
filename:要写入数据的文件。 data 为要写入的数据。 flags 可以是: FILE_USE_INCLUDE_PATH、FILE_APPEND或 LOCK_EX(LOCK_EX为独占锁定)
/* 首先使用 fwrite() 函数向05.txt 写入数据,再使用file_put_contents()函数 写入数据 */ $filepath = "05.txt"; $str = "此情可待成追忆 只是当时已惘然 <br>"; echo "用 fwrite 函数写入文件:"; $fopen = fopen($filepath, 'wb') or die('文件不存在'); fwrite($fopen, $str); fclose($fopen); readfile($filepath); echo "<p>用 file_put_contents 函数写入文件:" file_put_contents($filepath, $str); readfile($filepath);
1.3:操作文件——除了可以对文件内容进行读写,对文件本身同样也可以进行操作,如复制、重命名、查看修改日期等。PHP内置文件操作函数:
说明:在读写文件时,除了 file()、 readfile() 等少数几个函数外,其他操作必须要先使用 fopen() 函数打开文件,最后用 fclose() 函数关闭文件。文件的信息函数(如 filesize、 filemtime 等)则都不需要打开文件,只要文件存在即可。
2:目录处理——目录是一种特殊的文件。要浏览目录下的文件,首先要打开目录,浏览完毕之后,同样要关闭目录
1)打开/关闭 目录 —— 打开/关闭目录和打开/关闭 文件类似, 但打开的文件如果不存在, 就自动创建一个新文件,而打开的文件路径如果不正确,则一定会报错
A:打开目录—— opendir() 函数
resource opendir ( string path )
path是一个合法的目录路径,成功执行后返回目录的指针:如果path不合法或者因为权限或文件系统错误则不能打开目录,返回一个false 并产生一个 E_WARNING 级别的错误信息。可以在 opendir() 前面加上 "@" 符合来抑制错误信息的输出
B:关闭目录—— closedir()函数
void closedir( resource handle )
handle为使用opendir 函数打开的一个目录指针
$path = "D:\\Appserv\\www\\tm\\sl\\12"; if (is_dir ($path)){ //检测是否是一个目录 if ($dire = opendir($path)) //判断打开目录是否成功 echo $dire; //输出目录指针 }else{ echo '路径错误'; exit(); } ... //其他操作 closedir($dire); //关闭目录
2)浏览目录—— scandir() 函数
array scandir( string directory [, int sorting_order])
该函数返回一个数组,包含 directory 中的所有文件和目录。参数 sorting_order 指定排序顺序,默认按字母升序排序,如果添加了该参数,则变成降序
$path = 'F:\AppServ\www\tm\13'; //要浏览的目录 if (is_dir ($path)) { //判断文件名是否为目录 $dir = scandir($path); //使用scandir 函数取得所有文件及目录 foreach ($dir as $value ){ echo $value."<br>"; }else{ echo '目录路径错误!'; } }
3)操作目录—— 目录是特殊的文件,也就是说对文件的操作处理函数(如重命名)多数适用于目录。但还有些特殊函数只针对目录:
3:文件处理的高级应用—— 除了对文件可以进行基本的读写操作外,还可以对文件指针进行查找、定位,对正在读取的文件进行锁定等
1)远程文件的访问—— php支持URL格式的文件调用,只要在php.ini中配置一下即可。找到allow_url_fopen,设置ON
fopen('http://127.0.0.1/tm/sl/index.php', 'rb')
2)文件指针—— php可以实现文件指针的定位及查询,从而实现所需信息的快速查询。文件指针函数有: rewind()、 fseek()、 feof()和ftell()
A:rewind() 函数—— 该函数将文件 handle 的指针设为文件流的开头
bool rewind ( resource handle )
注意:如果将文件以附加 ("a")模式打开,写入文件的任何数据总是会被附加在后面,不论文件指针的位置在何处
B:fseek() 函数—— 实现文件指针的定位:
int fseek ( resource handle, int offset [, int whence ] )
handle:要打开的文件。offset 为指针位置或相对 whence 参数的偏移量,可以是负值
whence的值可以包括以下3中:
(1):SEEK_SET,位置等于offset 字节。默认
(2):SEEK_CUR,位置等于当前位置加上 offset 字节
(3):SEEK_END,位置等于文件尾加上 offset 字节。
C:feof() 函数—— 该函数判断文件指针是否在文件尾:
bool feof ( resource handle ) : 如果文件指针到了文件结束的位置,就返回 true, 否则返回 false
D:ftell() 函数 —— 该函数返回当前指针的位置:
int ftell ( resource handle )
$filename = '07.txt'; //指定文件路径及文件名 if (is_file($filename)){ //判断文件是否存在 echo "文件总字节数:".filesize($filename)."<br>"; $fopen = fopen($filename, 'rb'); //打开文件 echo "初始指针位置是:".ftell($fopen)."<br>"; //输出指针 fseek($fopen, 33); //移动指针 echo "使用fseek函数后指针位置:".ftell($fopen)."<br>"; echo "输出当前指针后面的内容:".fgets($fopen)."<br>"; if ( feof($fopen)) // 判断指针是否指向文件末尾 echo "当前指针指向文件末尾:".ftell($fopen)."<br>"; rewind($fopen); echo "使用rewind 函数后指针的位置:".ftell($fopen)."<br>"; echo "输出前33个字节的内容:".fgets($fopen, 33); fclose($fopen); }else{ echo "文件不存在"; }
3)锁定文件—— 在向一个文本文件写入内容时,需要先锁定该文件,以防止其他用户同时修改此文件内容
bool flock ( int handle, int operation)
handle 是一个已经打开的文件指针,operation 参数值如下:
$filename = '08.txt'; $fd = fopen($filename, 'w'); //以 w 形式打开文件 flock ($fd, LOCK_EX); // 锁定文件(独占共享) fwrite ($fd, "hightman1"); //向文件中写入数据 flock($fd, LOCK_UN); //解除锁定 fclose($fd); //关闭文件指针 readfile($filename); //输出文件内容
在向文件写入数据时,使用 w 或 w+ 选项来打开文件。这时如果使用了 LOCK_EX, 则同一时间访问此文件的其他用户无法得到文件的大小,也不能进行写操作
4:文件上传—— 文件上传可以通过HTTP 协议来实现。要实现文件上传功能,首先要在php.int 配置文件中对上传做一些设置,然后了解预定义变量 $_FILES, 通过$_FILES的值对上传文件做一些限制和判断,最后使用 move_uploaded_file() 函数实现上传
1)配置php.ini 文件
在php.ini 中找到 File Uploads 项:
A:file_uploads: on,服务器支持上传
B:upload_tmp_dir:上传文件临时目录
C:upload_max_filesize:服务器允许上传的文件的最大值,以MB为单位。默认2MB
除了File Uploads 项,还有几个属性也会影响到上传文件的功能
A:max_execution_time:PHP中一个指令所能执行的最大时间,单位为秒
B:memory_limit:PHP中一个指令所分配的内存空间,单位是MB
注意:如果使用集成化的安装包来配置PHP的开发环境,上述介绍的这些配置信息默认已经配置好了
如果要输出超大的文件,需要对php.ini 进行修改。包括 upload_max_filesize 的最大值, max_execution_time 和 memory_limit
2)预定义变量$_FILES——这个变量存储的是上传文件的相关信息,这个信息对于上传功能有很大的作用。该变量是一个二维数组:
3)文件上传函数—— move_uploaded_file() 函数
bool move_uploaded_file ( string filename, string destination )
成功返回true,否则返回false。filename 是上传文件的临时文件名,即 $_FILES[tmp_name]; destination 是上传后保存的新的路径和名称
注意:上传文件,创建form表单时,form的 enctype = "multipart/form-data"
<form action="" method="post" enctype="multipart/form-data" name="up_file" type="file" /> <input type="submit" name="submit" value="上传" /> </form> // 判断是否有上传文件 if (!empty ($FILES[up_file][name] )) { //将文件信息赋给变量 $fileinfo $fileinfo = $_FILES[up_file]; //判断文件大小 if ($fileinfo['size'] < 10000000 && $fileinfo['size'] > 0){ //上传文件 move_uploaded_file ($fileinfo['tmp_name'], $fileinfo['name'] ); echo "上传成功"; }else{ echo "文件太大或未知"; } }
4)多文件上传——php支持多文件上传,只要在表单中对文件上传域使用数组命名即可
<form action="" method="post" enctype="multipart/form-data"> <table id="up_table" border="1" bgcolor="f0f0f0"> <tbody id="auto"> <tr id="show"> <td>上传文件</td> <td><input name="u_file[]" type="file"></td> </tr> <tr> <td>上传文件</td> <td><input name="u_file[]" type="file"></td> </tr> </tbody> <tr><td colspan='4'><input type="submit" value="上传" /></td></tr> if (!empty($_FILES[u_file][name] )){ //将上传文件名另存为数组 $file_name = $_FILES[u_file][name]; //将上传的临时文件名存为数组 $file_tmp_name = $_FILES[u_file][tmp_name]; //循环上传文件 for ($i = 0; $i < count ($file_name); $i++ ){ //判断上传文件名是否为空 if ($file_name[$i] != ''){ move_uploaded_file ($file_tmp_name[$i], $i, $file_name[$i] ); echo '文件'.$file_name[$i].'上传成功。更名为'.$i.$file_name[$i].'<br>'; } } }