326 PHP完全参考手册 if(unlink(\
echo \ } . . . ?>
而如果在这个示例中文件没有被删除,phpunlink.php也会在代码中指出这一点:
Deleting files
Deleting files
if(unlink(\
echo \ }
else {
echo \ } ?>
结果如图9-15所示,其中文件已被删除。
图9-15 删除文件
9.17 使用函数fwrite写入文件
如果希望向一个文件写入字符串,可以使用函数fwrite:
第9章 文 件 处 理 fwrite (handle, string [, length])
327 将文件句柄、要写入的字符串和(可选的)要写入数据的最大长度传递给函数fwrite。该函数返回已写入的字节数;如果写入出错,则返回FALSE。
注意:
设置系统写入文件可能需要执行一些工作,因为这涉及文件系统保护。例如,在Windows系统中,需要右击写入的文件所在的文件夹,选择“属性”命令,单击“网络共享”选项卡,选择“共享文件夹”单选按钮并启用写入功能。在Unix系统中,确保对要写入的文件夹有写入特权。
在示例phpfwrite.php中将把文本写入文件data.txt。首先打开用于写入的文件:
$handle = fopen(\ . . . ?>
然后可以创建一个文本字符串$text以写入文件。注意,如果想写入多行文本,需要自行添加换行符:
$handle = fopen(\
$text = \ . . . ?>
接下来使用fwrite对文件执行写入操作:
$handle = fopen(\
$text = \
fwrite($handle, $text); ?>
为了完善上述代码,可以在phpfwrite.php中按照如下代码所示检查写操作是否失败:
$handle = fopen(\
$text = \
if (fwrite($handle, $text) == FALSE) {
328 PHP完全参考手册 echo \ } ?>
如果操作成功,可以按照如下代码所示告知用户:
Writing files
Writing files
$handle = fopen(\
$text = \
if (fwrite($handle, $text) == FALSE) { echo \ }
else {
echo \ }
fclose($handle); ?>
图9-16 对文件进行写操作
结果如图9-16所示,文件被成功写入。 下面是data.txt的内容:
第9章 文 件 处 理 Here is the text.
329 提示:
如果想在写入文件之前检查该文件是否可写,可以调用函数is_writable,将文件名传递给该函数;如果文件可写,该函数返回TRUE,否则返回FALSE。
9.18 读写二进制文件
可以使用函数fwrite写入二进制数据,并用函数fread读取数据,但是这两种方法都比较麻烦。可以使用函数pack将二进制数据包装为字符串,也可使用函数unpack将其恢复为二进制数据。
下面的示例phpwritebinary.php将数字512以二进制形式(非字符串)写入文件。首先按照如下代码所示打开文件进行二进制写入:
$number = 512;
$handle = fopen (\ . . . ?>
接下来,函数将数据包装为长整型格式,如下所示:
pack (\
下面是函数pack的格式,比如L就代表长整型: ● a:NULL填充的字节串 ● A:空格填充的字节串
● h:十六进制数,低四位字节优先 ● H:十六进制数,高四位字节优先 ● c:有符号字符 ● C:无符号字符
● s:有符号短整型(总是16位,机器字节序) ● S:无符号短整型(总是16位,机器字节序) ● n:无符号短整型(总是16位,大尾字节序) ● v:无符号短整型(总是16位,小尾字节序) ● I:有符号整型(机器相关大小和字节序) ● I:无符号整型(机器相关大小和字节序) ● l:有符号长整型(总是32位,机器字节序)
330 PHP完全参考手册 ● L:无符号长整型(总是32位,机器字节序) ● N:无符号长整型(总是32位,大尾字节序) ● V:无符号长整型(总是32位,小尾字节序) ● f:浮点数(机器相关大小和表示) ● d:双精度数(机器相关大小和表示) ● x:空字节
● X:倒退一个字节
● @:用NULL填充绝对位置
下面给出该示例如何向文件写入数据:
$number = 512;
$handle = fopen (\
if (fwrite ($handle, pack (\ . . . } ?>
最后,在phpwritebinary.php中,代码按照如下所示向用户指示操作成功与否:
Writing binary files
Writing binary files
$number = 512;
$handle = fopen (\
if (fwrite ($handle, pack (\ echo \ }
else {
echo \ }
fclose ($handle); ?>
本章讨论使用PHP来进行文件处理。在Web应用程序中,将数据存储在服务器上特别有用,因为这样可以使数据持久保存—— 也就是说,可以在页面访问之间保持可用。博客、客户名册、反馈页面都需要使用服务器上的文件。 本章将介绍多种PHP技术,首先介绍如何打开文件。 第 章 9文 件 处 理 9.1 使用fopen打开文件 与大多数语言一样,要想在PHP中处理文件,必须首先打开该文件。 $filehandle = fopen (filename, mode [, use_include_path [, zcontext]]) 在上面的函数调用中,filename是将要打开的文件的名称,mode指示如何打开文件(例如,从文件中读取或向文件写入),如果需要在PHP中搜寻带路径的文件,可以将use_include_path设置为1或TRUE。zcontext保存一个可选的文件上下文(上下文修改或增强数据流进或流出文件的行为)。下面是mode的可能值。 ● r: 以只读方式打开。 ● r+: 以读写方式打开。 ● w: 以只写方式打开,并且清除该文件的内容。如果文件不存在,则尝试创建它。 ● w+: 以读写方式打开,并且清除该文件的内容。如果文件不存在,则尝试创建它。 ● a: 以附加方式打开,如果文件不存在,则尝试创建它。 ● a+: 以读写方式打开,从文件末尾开始操作。如果文件不存在,则尝试创建它。 ● x: 创建并以只写方式打开,如果文件已存在,则fopen()调用失败并返回 FALSE。 ● x+: 创建并以读写方式打开,如果文件已存在,则 fopen()调用失败并返回 FALSE。 注意,不同的操作系统有不同的行结束约定。在编写文本文件并需要换行时,就必须使用用于该操作系统的正确的行结束字符。基于Unix的系统使用\\n作为行结束字符。基
302 PHP完全参考手册 于Windows的操作系统使用\\r\\n作为行结束字符。基于Macintosh的操作系统使用\\r作为行结束字符。
在Windows中,可以在操作文件时使用文本模式的转换标记(t)将\\n转换为\\r\\n。相应地,也可以使用b来强制执行二进制模式,二进制模式不会转换数据。要使用这些标识,需要指定b或t作为模式参数的最后一个字符,如wt。
当前,区分二进制模式和文本模式的所有平台的默认模式都被设置为二进制模式。如果脚本中存在问题,可尝试使用t标记。
下面的示例以只读模式打开文件/home/file.txt(可以在路径名中按照如下所示使用正斜杠,即使是在Windows中—— 也可以在执行转义的情况下使用反斜杠(\\\\)):
$handle = fopen(\
打开文件时就会得到一个文件句柄,文件句柄代表打开的文件。在接下来的操作中,使用这个句柄操作文件。注意,既然文件已被打开,就可以使用各种数据读取函数来读取文件,比如fread,后面将介绍这些数据读取函数。
下面的示例打开执行写入的文件:
$handle = fopen(\
下面的示例打开执行二进制写入的文件:
$handle = fopen(\
在Windows中,应该谨慎地转义用于文件路径中的反斜杠(或者使用正斜杠):
$handle = fopen(\
此处并不局限于本地文件系统的文件。下面给出打开不同Web站点上的文件的方法,使用URL来表示该文件:
$handle = fopen(\
也可以使用FTP协议打开文件:
$handle = fopen(\\
当打开文件时,就获得了可以操作的文件句柄。可以传递该文件句柄给其他操作文件的文件函数。
下面是一个示例。假设有一个文件file.txt,其中包含以下内容:
Here is your data.
在phpfopen.php中打开该文件以执行读取操作:
$handle = fopen(\
第9章 文 件 处 理 . . . ?>
303 如果打开操作失败,fopen会返回FALSE。因此,可以检查在phpfopen.php中是否按照如下代码所示打开文件:
Opening a file
Opening a file
$handle = fopen(\ if($handle){
echo \ } ?>
结果如图9-1所示,图中显示文件file.txt被成功打开。
图9-1 打开文件
也可以使用fopen函数打开Internet上的URL,为从网页中读取数据做准备:
$handle = fopen(\
现在文件已被成功打开—— 接下来如何读取其中的文本呢?
304 PHP完全参考手册 9.2 使用feof遍历文件内容
文件file.txt中有多行需要读取,下面给出如何每次一行地读取这些数据的方法。既然文件已被打开,那么如何遍历文件中的所有行呢?
方法是使用whille循环和feof函数。传递给feof函数一个文件句柄,如果到达文件末尾,该函数将返回true。下面是在phpread.php中如何逐行地遍历文件内容的方法:
Reading from a file
Reading from a file
$handle = fopen(\ while (!feof($handle)){ . . . } ?>
为了使这个循环运行,就必须真正地从文件读取数据(否则就永远不会到达文件末尾,而这个循环也永远不会终止)。可以使用fgets函数执行该操作。
9.3 使用fgets从文件中读取文本
使用fgets函数可以从文件中获得文本的字符串;按照如下方式使用该函数:
fgets (handle [, length])
传递给该函数对应于打开文件的文件句柄和可选的长度。根据相应的文件句柄,函数返回从文件读取的最多length-1字节的字符串。在遇到换行符(包括在返回值中)、文件结束或者已经读取length-1字节时(无论首先发生何种情况),读取操作就会结束。如果没有指定长度,则长度默认为1024 字节。
下面给出在phpread.php中从文件file.txt读取一行文本的代码:
$handle = fopen(\
第9章 文 件 处 理 while (!feof($handle)){ $text = fgets($handle); . . . } ?>
305 也可以逐行地回送已读取的文本:
Reading from a file
Reading from a file
$handle = fopen(\ while (!feof($handle)){ $text = fgets($handle); echo $text, \ } ?>
现在已经打开文件并从中读取了数据。下一步要做的工作是完成文件读取操作—— 即关闭文件。
9.4 关闭文件
在PHP中,当处理完一个文件后应该关闭该文件。文件的关闭操作可以释放与文件相关的资源,而且避免之后代码中因为重复利用文件句柄变量而可能导致的冲突。
为了关闭文件,可按如下方式使用fclose函数:
fclose($filehandle);
如果文件被成功关闭,该函数就返回TRUE,否则返回FALSE。 下面给出fclose函数在phpread.php中的使用方法:
Reading from a file
第9章 文 件 处 理 下面有一个.ini示例文件sample.ini(注意,如果在.ini文件中需要添加注释,必须在注释前使用分号):
; This is a sample .ini file
[first_section] first_color = red second_color = white third_color = blue
[second_section]
file = \URL = \
321 下面的示例phpparseinifile.php给出读取sample.ini的方法。将sample.ini中的内容读入数组$array:
$array = parse_ini_file(\ . . . ?>
使用数组$array恢复.ini文件中的值。例如,可以按照如下所示恢复键first_color下的值(即“red”): $array[\。在这个示例中,可以遍历数组,并输出键和它们的值:
Parsing .ini files
Parsing .ini files
$array = parse_ini_file(\
foreach ($array as $key => $value) { echo \ } ?>
结果如图9-12所示,文件sample.ini中的数据被读入并显示。
322 PHP完全参考手册
图9-12 解析.ini文件
9.13 使用stat函数获取文件信息
stat函数用来给出文件的相关信息:
stat (filename )
该函数返回包含文件信息的数组,而这些信息大多在Unix机器上有意义。下面是存储在带数字索引(也可以使用此处给出的圆括号中的文本值)的返回数组中的数据:
● 0 (dev):设备号 ● 1 (ino):信息节点号 ● 2 (mode):节点保护模式 ● 3 (nlink):链接数目
● 4 (uid):所有者的用户ID ● 5 (gid):所有者的组ID
● 6 (rdev):设备类型,如果是信息节点设备的话 ● 7 (size):文件的大小(字节)
● 8 (atime):最近访问时间 (Unix 时间标记) ● 9 (mtime):最近修改时间 (Unix时间标记)
● 10 (ctime):最近信息节点改变时间 (Unix时间标记) ● 11 (blksize):文件系统I/O的块大小 ● 12 (blocks):所分配块的数量
大部分项只在Unix系统中有意义;如果在Windows系统中没有对应项,系统会返回值-1。
下面的示例phpstat.php将使用这些项,该示例报告文件file.txt的大小。通过对文件file.txt使用stat函数来开始这个示例:
$array = stat(\ .
第9章 文 件 处 理 . . ?>
323 可以查找文件file.txt的大小并按如下方式显示:
Using stat
Using stat
$array = stat(\
echo \ ?>
结果如图9-13所示,图中显示了文件的大小。
图9-13 查找文件大小
9.14 使用函数fseek设置文件指针的位置
PHP使用文件指针来跟踪其在文件中的位置和下一次读写操作将在何处执行。例如,在打开一个文件时,文件指针被设置在文件的起始位置;而在打开文件添加数据时,文件指针就被设置到文件的末尾。可以使用函数fseek设置文件指针的位置:
fseek(handle, offset, [start_point]);
其中,handle是需要设置文件指针的文件的句柄,offset是需要设置的文件指针的偏移
324 PHP完全参考手册 字节数,而start_point指示文件指针的起始点,可以为以下常量之一:
● SEEK_SET:文件的起始点 ● SEEK_CUR:指针的当前位置 ● SEEK_END:文件的结尾 offset也可以设置为负值。
9.15 使用函数copy复制文件
可以使用函数copy复制文件:
copy (source, destination)
其中,source是源文件名,destination是副本名(如果适用的话,可包含路径名)。如果操作成功,该函数返回TRUE,否则返回FALSE。
使用下面的示例phpcopy.php复制文件file.txt,其副本为copy.txt:
$file = 'file.txt'; $copy = 'copy.txt'; . . . ?>
下面的代码尝试复制文件并在执行后给出复制成功的提示:
$file = 'file.txt'; $copy = 'copy.txt';
if (copy($file, $copy)) { echo \ } . . . ?>
如果复制操作失败,同样也可以按如下方式在phpcopy.php中给出复制失败的提示:
Copying files
第9章 文 件 处 理
Copying files
$file = 'file.txt'; $copy = 'copy.txt';
if (copy($file, $copy)) { echo \ }
else {
echo \ } ?>
325 结果如图9-14所示,此处按计划实现了文件复制操作。 注意:
如果想要移动文件,可以使用rename函数。
图9-14 复制文件
9.16 使用函数unlink删除文件
可以使用函数unlink删除文件:
unlink (filename [, context] )
其中,filename是指文件名,而context是一个可选上下文。如果文件成功删除,函数返回TRUE,否则返回FALSE。
查看下面的示例phpunlink.php。如果代码成功执行删除文件copy.txt的操作,将会指示如下信息:
第9章 文 件 处 理 Reading a whole file at once
$text = file_get_contents(\
$fixed_text = str_replace(\
echo $fixed_text; ?>
311
图9-5 一次性读取整个文件
9.7 使用file将文件读入数组
可以使用file函数一次性将整个文本读入一个数组;每行会成为数组中的一个元素。下面是file函数的使用方法:
file (filename [, use_include_path [, context]] )
其中,filename是要读取的文件名,如果需要在PHP包含路径中搜索文件,可以将use_include_path设置为TRUE,context是操作的上下文。该函数返回数组或在操作失败时返回FALSE。
如果需要编写自己的数据库文件,该函数将极其有用。假设需要在一个数据库文件中保存学生的分数—— 就可以只使用一条语句将所有分数读入一个数组。
下面的示例phpfarray.php将整个file.txt读入数组$data。首先将文件内容加载进数组:
$data = file('file.txt'); . . . ?>
312 PHP完全参考手册 现在已经将整个文件读入$data数组。file.txt文件中的每行都是$data数组中的一个元素。
现在可以使用foreach循环显示数组中的数据:
$data = file('file.txt');
foreach ($data as $line) { . . . } ?>
下面唯一要做的工作是显示每一行:
$data = file('file.txt');
foreach ($data as $line) { echo $line , \ } ?>
事实上,还可以显示行号。下面给出在phpfarray.php中如何执行该操作:
Reading a file into an array
Reading a file into an array
$data = file('file.txt');
foreach ($data as $number => $line) {
echo \ } ?>
结果如图9-6所示,图中表明整个文件file.txt都被读入数组并显示。
也可以使用file函数打开网页并将其读入数组。下面的示例phpurlarray.php就读入http://www.php.net页面并显示:
第9章 文 件 处 理
Reading a Web page into an array
Reading a Web page into an array
$data = file('http://www.php.net');
foreach ($data as $number => $line) {
echo \ } ?>
313
图9-6 将文件读入数组
部分结果如图9-7所示,程序读入URL并且逐行显示它的HTML内容。
图9-7 把一个URL读入数组
314 PHP完全参考手册 有一点需要注意的是,数组中的每个元素在结尾处仍然有一个换行符。如果想删除这个换行符,可以使用PHP的rtrim函数
9.8 使用file_exists函数检查文件是否存在
如果试图操作一个根本不存在的文件,将会得到错误提示。为了防止此类错误,可以使用file_exists函数来检查文件是否存在:
file_exists (filename )
传递给该函数一个文件名(可以包含路径),如果文件存在,它就会返回TRUE;否则返回FALSE。
下面的示例phpfileexists.php对一个不存在的文件does_not_exist.txt进行检查:
$filename = \ . . . ?>
代码接下来检查文件是否存在:
$filename = \
if (file_exists($filename)) { . . . } . . . ?>
如果文件存在,可以将其读入并显示它的内容:
$filename = \
if (file_exists($filename)) { $data = file($filename);
foreach ($data as $number => $line) {
echo \ } } .
第9章 文 件 处 理 . . ?>
315 如果文件不存在,可以显示一条消息以屏蔽来自PHP的错误消息:
Checking if a file exists
Checking if a file exists
$filename = \
if (file_exists($filename)) { $data = file($filename);
foreach ($data as $number => $line) {
echo \ } }
else {
echo \ } ?>
结果如图9-8所示,该示例在尝试打开文件之前就判断出文件不存在,因此不会生成错误。
图9-8 检查文件是否存在
316 PHP完全参考手册 9.9 使用filesize获得文件大小
filesize函数的返回值是一个整数,可以通过它来获得文件的大小:
filesize (filename )
只需传递一个文件名(如果需要的话,可以包含路径)给filesize函数,就可以返回一个整数值;如果文件不存在,该函数返回FALSE。
下面的示例phpfilesize.php可以显示file.txt的大小:
Getting file size
Getting file size
echo \file file.txt is \filesize(\\long.\ ?>
结果如图9-9所示,该示例确定文件file.txt的大小为24字节。
图9-9 获得文件尺寸
对于文本文件的处理,本章已经介绍了很多相关内容—— 那么如何处理二进制文件呢?
第9章 文 件 处 理 317 9.10 使用fread读取二进制文件
到目前为止,所介绍的文件都作为文本文件被处理,但是使用像fread这样的函数以二进制方式处理文件也很简单:
fread (handle, length)
该函数从handle引用的文件中最多读取length个字节。 该函数在读取完length字节或到达EOF(文件结尾)时就会停止读取。
在类似于Windows这样的系统中,应该以二进制读取方式(即rb模式)打开文件以操作fread。因为添加字母b到模式中不会对其他系统造成影响,所以此处从可移植性方面考虑添加该字母。下面的示例phpfread.php将file.txt视为二进制文件。
下面的示例首先以二进制读取方式打开文件file.txt:
$handle = fopen(\ . . . ?>
可以使用filesize确定文件大小,并使用函数fread将其读入变量$text:
$handle = fopen(\
$text = fread($handle, filesize(\ . . . ?>
可以使用
元素来代替换行符:
$handle = fopen(\
$text = fread($handle, filesize(\
$fixed_text = str_replace(\ . . . ?>
回送$text,强制PHP将其视为文本处理:
$handle = fopen(\
318 PHP完全参考手册 $text = fread($handle, filesize(\
$fixed_text = str_replace(\
echo $fixed_text; . . . ?>
剩下要做的就是关闭文件,如同下面的phpfread.php所示:
Reading binary data
Reading binary data
$handle = fopen(\
$text = fread($handle, filesize(\
$fixed_text = str_replace(\
echo $fixed_text;
fclose($handle); ?>
结果如图9-10所示,该示例使用二进制读取操作读取文件file.txt。
图9-10 读取二进制数据
第9章 文 件 处 理 319 9.11 使用fscanf解析文件
可以使用函数fscanf解析文件:
fscanf (handle, format)
该函数获得一个文件句柄以及一个与用于sprintf函数的类型相同的格式化字符串。 下面的示例phpfscaf.php读取文件actors.txt。在该文件中,通过制表符分隔演员的名和姓:
Cary Grant Myrna Loy
Jimmy Stewart June Allyson
该示例首先打开文件actors.txt:
$handle = fopen(\ . . . ?>
这里的格式是\字符串、制表符、字符串、换行符),因此下面给出使用while循环来解析文件中的一行数据并将其读入到$name数组的方法:
$handle = fopen(\
while ($name = fscanf($handle, \ . . . } ?>
接下来,将数组$name中的值赋给变量$firstname和$lastname,然后显示这些姓名:
Parsing files
Parsing files
320 PHP完全参考手册
$handle = fopen(\
while ($name = fscanf($handle, \ list ($firstname, $lastname) = $name; echo $firstname, \ }
fclose($handle); ?>
结果如图9-11所示,程序解析文件actors.txt并且显示该文件中的数据。
图9-11 解析文件数据
9.12 使用parse_ini_file解析ini文件
与函数fscanf类似,parse_ini_file也用于解析文件(此处是.ini初始化文件)。下面是使用parse_ini_file的方式:
parse_ini_file (filename [, process_sections] )
该函数载入一个由filename指定的ini文件,并将其中的设置作为联合数组返回。将最后的process_sections参数设置为TRUE,可得到一个多维数组,该数组包括文件中的部分名和设置。process_sections的默认值是FALSE。
注意,该函数不能用于PHP自身使用的初始化文件php.ini,在PHP启动之前就已经解析和读取了该文件。
警告:
有些保留字不可以作为ini文件中的键,这些保留字包括:null、yes、no、true和false。值null、no和false等效于“”,yes和true等效于“1”。字符{}|&~![()\不能用在键中的任何地方。
第9章 文 件 处 理 结果如图9-17所示,显示二进制文件被写入。
331
图9-17 写入二进制文件
要想从文件读取二进制数据,可以在phpbinaryread.php中使用unpack函数。首先,打开进行二进制读取的文件:
$handle = fopen (\ . . . ?>
然后使用函数fread读取二进制数据,并且指示需要4个字节(长整型整数的长度):
$handle = fopen (\ $data = fread ($handle, 4); . . . ?>
接下来使用函数unpack把数据还原到一个数组中,该数组在索引data下带有包含长整型值的元素。
$handle = fopen (\ $data = fread ($handle, 4);
$array = unpack (\ . . .
?>
现在可以使用键“data”从数组中恢复二进制数据:
332 PHP完全参考手册
$handle = fopen (\ $data = fread ($handle, 4);
$array = unpack (\ $data = $array[\ . . . ?>
最后,在phpbinaryread.php中显示该数据:
Reading binary files
Reading binary files
$handle = fopen (\ $data = fread ($handle, 4);
$array = unpack (\ $data = $array[\
echo \ ?>
结果如图9-18所示,程序从文件data.dat中成功读取了二进制数据。
图9-18 从二进制文件中读取数据
第9章 文 件 处 理 333 9.19 使用函数fwrite将数据附加到文件中
如果想要打开文件以显式地附加数据,也可以使用函数fwrite将数据附加到文件中。下面的示例phpappend.php将一些文本附加到文件data.txt中。首先打开用于附加数据的文件data.txt:
$handle = fopen(\ . . . ?>
下面是要附加到文件中的文本:
Here is more text.
可以将该文本放入变量$text:
$handle = fopen(\
$text = \ . . . ?>
使用函数fwrite将文本附加到data.txt中—— 如果操作失败,则会提示用户:
$handle = fopen(\
$text = \
if (fwrite($handle, $text) == FALSE) { echo \ } . . . ?>
另一方面,如果附加操作成功,在phpappend.php按如下方式提示用户:
334 PHP完全参考手册
Appending to files
Appending to files
$handle = fopen(\
$text = \
if (fwrite($handle, $text) == FALSE) { echo \ }
else {
echo \ }
fclose($handle); ?>
结果如图9-19所示,图中显示文件被成功附加数据。
图9-19 附加到文件
以下是data.txt的新内容:
Here is the text. Here is
第9章 文 件 处 理 more text.
335 提示:
如果想要执行相反的操作(截取文件),可以使用函数ftruncate指定文件的新大小:
ftruncate (handle, size)
9.20 使用函数file_put_contents一次性写入文件
如果想将文本写入文件,可以使用一种快捷方法—— 使用file_put_contents函数。该函数将字符串写入文件,下面给出这个函数通常的使用方法:
file_put_contents (filename, data [, flags [, context]])
其中,filename是要写入文件的名称,data是要写入的字符串文本,flags可以是FILE_USE_INCLUDE_PATH或FILE_APPEND,而context是文件上下文。函数返回将要写入文件的字节数;如果未能写入到文件,则返回FALSE。
使用这个函数等同于自动调用fopen、 fwrite和fclose这三个函数—— 而无须再亲自打开和关闭文件,并且不需要文件句柄。下面是一个示例phpfileputcontents.php。首先给出要写入文件的文本:
$text = \ . . . ?>
接下来,使用函数file_put_contents将本文写入文件data.txt:
$text = \
file_put_contents(\ . . . ?>
如前所述,可以对代码进行改进,对来自函数的返回值进行检查。如果有问题,则提示用户:
$text = \
if (file_put_contents(\
336 PHP完全参考手册 echo \ } . . . ?>
否则,也可以在phpfileputcontents.php中按照如下代码所示在操作成功时提示用户:
Writing files with file_put_contents
Writing files with file_put_contents
$text = \
if (file_put_contents(\ echo \ }
else {
echo \ } ?>
注意,不需要关闭文件(或打开文件,就此例而言)。结果如图9-20所示,表明已经创建了文件。
图9-20 使用file_put_contents写入文件
第9章 文 件 处 理 337 9.21 锁定文件
在多用户环境(例如Web服务器)中,多个用户可能同时访问脚本—— 这就意味着相同脚本的多个副本在同时运行。如果脚本访问文件,在两个脚本或相同脚本的两个副本尝试同时写入同一个文件时,就会产生冲突。为了解决这个问题,可以使用文件锁定函数flock:
flock (handle, operation [, &wouldblock] )
其中,handle是要锁定文件的句柄,而operation可以有以下几种值:
● 要获得共享锁(读取程序),可将operation设为LOCK_SH ● 要获得独占锁(写入程序),可将operation设为LOCK_EX ● 要释放锁(共享锁或独占锁),可将operation设为LOCK_UN 如果锁被阻塞,可选的第三个参数将被设置为TRUE。 如果获得一个锁,函数将返回TRUE,否则返回FALSE。
用户能以咨询方式锁定文件—— 所有文件访问代码必须查看是否可以在访问文件之前获取文件的锁。如果代码不能获取文件的锁,则表明其他一些代码正在使用该文件,当前代码就必须等待。锁采用咨询方式(而在Windows下,锁采用强制方式),这就意味着其他代码能够操作锁定的文件—— 而这可能会把事情搞得很糟糕—— 所以必须确保在写入文件之前尝试获取锁。在完成对文件的操作后,解除锁定文件,从而使其他代码可以访问该文件。
函数flock通常阻塞(即不返回),直到获得安全的锁。如果不想等待—— 并且可能挂起代码—— 则应该对常量LOCK_NB和该操作执行OR操作,例如:LOCK_EX | LOCK_NB。这将使函数flock立刻返回。而如果没有获取锁,可以等待1秒钟(像下面这样使用PHP的sleep函数:sleep(1),该函数将使代码暂停1秒钟),然后再尝试。尝试15次之后将超时。
下面这个示例phpflock.php在写入文件data.txt之前就锁定该文件。打开文件,像下面这样尝试获得锁:
$handle = fopen(\
$text = \
if (flock($handle, LOCK_EX | LOCK_NB)) { . . . } ?>
如果获得锁,就可以写入该文件,然后对该文件解除锁定:
$handle = fopen(\
338 PHP完全参考手册 $text = \
if (flock($handle, LOCK_EX | LOCK_NB)) { echo \
if (fwrite($handle, $text) == FALSE) { echo \ }
else {
echo \ }
flock($handle, LOCK_UN);
echo \ } ?>
这段代码只尝试锁定文件一次。如果不能锁定文件,将立即显示错误。可以遍历15或20秒钟,尝试继续锁定文件直至放弃。
如果不能获得锁,则表明其他代码正在使用这个文件,在phpflock.php中应该像下面这样提示用户:
Locking and unlocking files
Locking and unlocking files
$handle = fopen(\
$text = \
if (flock($handle, LOCK_EX | LOCK_NB)) { echo \
if (fwrite($handle, $text) == FALSE) { echo \ }
else {
echo \ }
flock($handle, LOCK_UN);
echo \ }
else {
echo \ }
第9章 文 件 处 理
fclose($handle); ?>
339 现在就完成了所有操作。结果如图9-21所示,其中显示了锁定文件,然后写入文件,最后解锁文件。
图9-21 锁定并写入文件
记住,如果不能获得文件的锁,很可能是其他代码正在使用这个文件,应该过一段时间再尝试锁定操作。