您的位置:首页 > 编程语言 > PHP开发

PHP 中的文件处理技术

2016-05-09 10:41 344 查看
第5 章 PHP 中的文件处理技术

文件处理技术是一种编程语言的基本处理能力之一。本章将介绍PHP 中的各种文件处理

技术和技巧。虽然很多数据都是保存在数据库中,但是文件管理依然占据着重要的地位。

文件处理一般包含以下一些步骤。

(1)打开文件。打开指定的文件,如果该文件不存在,则创建该文件。

(2)文件操作。在打开文件之后,就可以对该文件进行各种操作。如果文件中已经包含

数据,则可以从中读取数据,重新向文件写入数据,或者向文件中添加数据。

(3)关闭文件。在完成处理文件之后,需要关闭该文件。

PHP 中提供了许多与文件相关的函数,可以用来将网页上的数据保存到文件,将文件中的数

据检索到网页,或者仅仅修改已有的文件数据,或者添加新数据。其中最常用的文件操作如下:

(1)检查文件是否存在;

(2)打开文件;

(3)读取文件;

(4)向文件中写入数据。

下面详细介绍以上的操作。

5.1 检测文件或者目录是否存在

在PHP 中,可以通过函数file_exists 来检测一个文件或者目录是否存在。该函数声明

如下:

bool file_exists ( string filename)

如果由filename 指定的文件或目录存在则返回TRUE,否则返回FALSE。

提示

在Windows 中要用//computername/share/filename 或者\\computername\share\filename

来检查网络中的共享文件。

实例 5-1 检测文件是否存在

本实例使用file_exists 函数检测文件是否存在,如代码5-1 所示。

【代码 5-1】 file_exists.php

<?php

$filename = 'hello.txt';

$catalog="hello";

//文件检测

第5 章 PHP 中的文件处理技术 161

if (file_exists($filename)) {

print $filename."文件存在!<br>";

} else {

print $filename."文件不存在!<br>";

}

//目录检测

if (file_exists($catalog)) {

print $catalog."目录存在!";

} else {

print $catalog."目录不存在!";

}

?>

file_exists.php 文件的执行结果如图5-1 所示。

图 5-1 file_exists.php 文件的执行结果

由于笔者已在当前目录下创建了目录“hello”,所以执行结果显示该目录存在,而当前目

录下没有“hello.txt”文件,因此提示文件不存在。

5.2 打 开 文 件

任何对文件的操作都必须先要打开该文件。

在 PHP 中,打开一个文件使用的函数是fopen。

fopen 函数的声明如下所示:

int fopen ( string filename, string mode [, int use_include_path [, resource

zcontext]])

调用fopen 函数的时候,需要传递2 个、3 个或者4 个参数。通常使用两个参数。其中

第一个参数filename 表示要打开的文件名,而第二个参数mode 表示打开的方式。不同的打

开方式,可以进行的操作是不一样的。

fopen()将filename 指定的名字资源绑定到一个流上。如果filename 是“scheme://...”的

格式,则被当成一个URL,PHP 将搜索协议处理器(也被称为封装协议)来处理此模式。如

果该协议尚未注册封装协议,PHP 将发出一条消息来帮助检查脚本中潜在的问题并将

filename 当成一个普通的文件名继续执行下去。

如果 PHP 认为filename 指定的是一个本地文件,将尝试在该文件上打开一个流。该文件

必须是PHP 可以访问的,因此需要确认文件访问权限是否允许该访问。如果激活了安全模式

或者open_basedir 则会应用进一步的限制。

如果 PHP 认为filename 指定的是一个已注册的协议,而该协议被注册为一个网络URL,

PHP 将检查并确认allow_url_fopen 已被激活。如果关闭了,PHP 将发出一个警告,而fopen

的调用则失败。

可以这样理解,如果参数 filename 以http://开头,则表示打开的是远程Web 服务器上的

文件,如果以ftp://开头,则表示要从远程FTP 服务器上获取文件,并需要与指定的服务器建

162 PHP 网络编程技术与实例

立 FTP 会话。如果前面没有任何前缀,一般情况下表示打开本地文件。

第 2 个参数mode 有多种取值,用来指示文件是读、写还是附加。mode 参数的具体取值

如表5-1 所示。

表 5-1 fopen 函数中mode 的可能值列表

mode 说 明

'r' 只读方式打开,将文件指针指向文件头

'r+' 读写方式打开,将文件指针指向文件头

'w' 写入方式打开,将文件指针指向文件头并将文件大小设为零。如果文件不存在则尝试创建

'w+' 读写方式打开,将文件指针指向文件头并将文件大小设为零。如果文件不存在则尝试创建

'a' 写入方式打开,将文件指针指向文件末尾。如果文件不存在则尝试创建

'a+' 读写方式打开,将文件指针指向文件末尾。如果文件不存在则尝试创建

'x'

创建并以写入方式打开,将文件指针指向文件头。如果文件已存在,则fopen()调用失败并返回FALSE,生成一

条E_WARNING 级别的错误信息。如果文件不存在则尝试创建。这和给底层的open(2)系统调用指定

O_EXCL|O_CREAT 标记是等价的。此选项仅能用于本地文件

'x+'

创建并以读写方式打开,将文件指针指向文件头。如果文件已存在,则fopen()调用失败并返回FALSE,并生成

一条E_WARNING 级别的错误信息。如果文件不存在则尝试创建。这和给底层的open(2)系统调用指定

O_EXCL|O_CREAT 标记是等价的。此选项仅能用于本地文件

'b'

二进制模式。用于与其他模式进行连接。如果文件系统能够区分二进制文件和文本文件,可能会使用它。Windows

系统可以区分;而Unix 系统则不区分。推荐一直使用这个选项,以便获取最大程度的可移植性。二进制模式是

默认的模式

't' 用于与其他模式的结合。这个模式只是Windows 系统下的一个选项。不是推荐选项,除非曾经在代码中使用了

b 选项

提示

如果指定的文件需要从远程的HTTP 服务器上获取,则只能以只读方式打

开。这样可以有效地防止他人篡改网页。类似地,如果需要从FTP 服务器上

获取指定的文件,则只能以写或者读的方式打开,但不能同时以写和读的方式

打开。

在一些情况下,可能会遇到方式 b,这种方式只适合一定的平台,如windows,它能区

分文本和二进制格式。这种方式在诸如UNIX 的平台上不起作用。

注意

不同的操作系统产品具有不同的行结束习惯。当写入一个文本文件并想插

入一个新行时,需要使用符合操作系统的行结束符号。基于UNIX 的系统使用

\n 作为行结束字符,基于Windows 的系统使用\r\n 作为行结束字符,基于

Macintosh 的系统使用\r 作为行结束字符。如果写入文件时使用了错误的行结

束符号,则其他应用程序打开这些文件时可能导致数据发生改变,不是原来写

入的数据。

fopen 的第3 个参数use_include_path 是可选的,在按照由该参数指定的路径下查找文件

时使用它。如果希望在php.ini 文件中设定的include_path 路径中进行查找,则只需要将该参

数设置为1。

常用的打开文件的方法如代码 5-2 所示。

【代码 5-2】

<?php

//只读方式打开文本文件,该文件路径为相对当前PHP 文件的路径

$handle = fopen ("/home/rasmus/file.txt", "r");

第5 章 PHP 中的文件处理技术 163

//只写方式打开二进制文件,该文件路径为相对当前PHP 文件的路径

$handle = fopen ("/home/rasmus/file.gif", "wb");

//打开远程WEB 服务器文件

$handle = fopen ("http://www.example.com/", "r");

//打开远程FTP 文件

$handle = fopen ("ftp://user:password@example.com/somefile.txt", "w");

//打开本地机器上的绝对路径的文件,该种方式适合Unix 系统和Windows 系统

$handle = fopen ("c:/data/info.txt", "r");

//打开本地机器上的绝对路径的文件,该种方式适Windows 系统,如果使用反斜线,必须使用转义符

//即双反斜线

$handle = fopen ("c:\\data\\info.txt", "r");

?>

如果用户以“w”或者“a”模式打开一个文件时,该文件不存在,则系统会自动创建该

文件。

实例 5-2 创建文件

本实例通过fopen 函数创建一个文件,如代码5-3 所示。

【代码 5-3】 createfile.php

<?php

//在hello 目录下创建一个1.txt 文件,以只写模式创建

$handle = fopen ("hello/1.txt", "w");

//关闭文件,使用fclose 函数

fclose($handle);

echo "/hello/1.txt 文件创建成功!<br>";

//在C 盘根目录下创建一个temp.txt 文件,以追加模式创建

$handle=fopen("c:/temp.txt","a");

//同样也要关闭文件

fclose($handle);

echo "c:/temp.txt 文件创建成功!";

?>

createfile.php 文件的执行结果如图5-2 所示。

图 5-2 createfile.php 文件的执行结果

执行代码 5-3 后,可以去C 盘根目录下查看刚才创建的temp.txt 文件,同时也可以在当

前目录的子目录“hello”下创建了1.txt 文件。注意,要确保“hello”目录已经创建。

以上代码中虽然创建了文件,但是整个文件是空的,因此接下来的步骤是向文件中添加数据。

5.3 写入或者追加数据

5.3.1 写入数据

在PHP 中,写文件的函数有好几个,最常用的函数为fwrite(),也可以使用fputs()函数,

该函数是fwrite()函数的别名函数(两者的用法一样)。

164 PHP 网络编程技术与实例

fwrite()函数的声明如下:

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

fwrite()把string 的内容写入文件指针handle 处。如果指定了length,当写入了length 个

字节或者写完了string 以后,写入就会停止。

fwrite()返回写入的字符数,出现错误时则返回FALSE。

注意

如果给出了 length 参数,则magic_quotes_runtime 配置选项将被忽略,而

string 中的斜线将不会被去掉。

实例 5-3 将数据写入文件

本实例以只写方式打开一个文件,然后向文件中写入一行文字,如代码5-4 所示。

【代码 5-4】 writedata.php

<?php

$filename = 'hello/1.txt';

$somecontent = "我先被写入的!\r\n";

$somecontent1 = "我后被写入的!\r\n";

// 首先要确定文件存在并且可写

if (is_writable($filename)) {

// 在这个例子里,将使用只写模式打开$filename

// 文件指针将会在文件的开头,如果原来文件中有其他数据,则会被删除

if (!$handle = fopen ($filename, "w")) {

print "不能打开文件 $filename";

exit;

}

// 将$somecontent 写入到打开的文件中

if (!fwrite($handle, $somecontent)) {

print "不能写入到文件 $filename";

exit;

}

print "成功地将\" $somecontent \"写入到文件$filename<br>";

fclose($handle);

$handle = fopen ($filename, "w"); //再次打开

//继续打开文件写入另外一个字符串,原来写入的数据则被清除

fwrite($handle, $somecontent1);

fclose($handle);

print "成功地将\" $somecontent1 \"写入到文件$filename";

} else {

print "文件 $filename 不可写";

}

?>

writedata.php 文件的执行结果如图5-3 所示。

从图 5-3 中可以看出,虽然两句话都被写入到文件中,而实际上只有最后一句话被写入

到文件了,如图5-4 所示。

这是因为采用了只写模式打开,每次写入新数据的时候,原始数据都会被删除。

第5 章 PHP 中的文件处理技术 165

图 5-3 writedata.php 的执行结果图 5-4 最终被写入的数据

实例 5-4 写入多行数据

本实例实现一次将多行数据写入文件,如代码5-5 所示。

【代码 5-5】 writedata1.php

<?php

$filename = 'hello/2.txt';

$handle = fopen ($filename, "w");

fwrite($handle, "1\r\n");

fwrite($handle, "2\r\n");

fwrite($handle, "3\r\n");

fwrite($handle, "4\r\n");

fwrite($handle, "5\r\n");

fwrite($handle, "6\r\n");

fwrite($handle, "7\r\n");

fwrite($handle, "8\r\n");

fclose($handle);

?>

执行代码5-5 后,会创建2.txt 文件,2.txt 文件的内容如图5-5 所示。

图 5-5 写入多行文本

从图 5-5 中可以看出,打开一个文件后可以一次写入多行文本。

提示 \r\n 在Windows 中表示字符串结束并且换行。

5.3.2 追加数据

前面介绍了向文件中写入数据,但是每次重新打开文件后,都会删除原来的数据,这样

很不方便。比如要将一些个人的基本信息保存在一个文本文件中,但不是一次性写入,而是

需要经常打开文件追加,这个时候,就需要使用追加模式来写入数据。

实例 5-5 追加数据

本实例实现打开一个已有文件,然后追加数据,如代码5-6 所示。

166 PHP 网络编程技术与实例

【代码 5-6】 appenddata.php

<?php

$filename = 'hello/student.txt';

$student1 = "姓名:小狗 \t 年龄:5 \t 性别:男\r\n";

$student2 = "姓名:小猫 \t 年龄:4 \t 性别:女\r\n";

$student3 = "姓名:小猪 \t 年龄:3 \t 性别:男\r\n";

// 在这个例子里,首先使用只写模式模式打开$filename

if (!$handle = fopen ($filename, "w")) {

print "不能打开文件 $filename";

exit;

}

// 将$student1 写入到打开的文件中

if (!fwrite($handle, $student1)) {

print "不能写入到文件 $filename";

exit;

}

//fwrite($handle, $student1);

print "成功地将\" $student1 \"写入到文件 $filename<br>";

fclose($handle);

$handle = fopen ($filename, "a"); //接着以添加模式打开文件

//继续添加其他信息

fwrite($handle, $student2);

print "成功地将\" $student2 \"写入到文件 $filename<br>";

fwrite($handle, $student3);

print "成功地将\" $student3 \"写入到文件 $filename<br>";

fclose($handle);

?>

appenddata.php 文件的执行结果如图5-6 所示。

图 5-6 appenddata.php 文件的执行结果

打开刚才创建的 student.txt,可以看到如图5-7 所示结果。

图 5-7 添加数据成功

5.4 关 闭 文 件

任何文件在打开操作后都必须关闭,否则可能会引起错误。在前面的例题中,其实已经

使用了关闭文件函数,即fclose()函数。fclose()函数的声明如下:

第5 章 PHP 中的文件处理技术 167

bool fclose ( resource handle)

fclose 函数将handle 指向的文件关闭。如果成功则返回TRUE,失败则返回FALSE。

提示 文件指针必须有效,并且是通过 fopen()或fsockopen()成功打开的。

简单示例如代码 5-7 所示。

【代码 5-7】

<?php

$handle = fopen('somefile.txt', 'r');

fclose($handle);

?>

5.5 读 取 数 据

前面介绍了如何创建文件、打开文件以及向文件中写入数据以及追加数据,接下来将介

绍如何从文件中读取数据。

5.5.1 读取一行数据

打开文件后,如果要逐行读取文件内容,可以使用下面的函数。

(1)ftets 函数。该函数的声明如下:

string fgets(int handle [, int length])

其中handle 参数是被打开的要读取数据的句柄,而length 参数表示要读取的数据长度。

该函数的作用是从handle 指向的文件中读取一行并返回长度最多为length−1 字节的字符串。

遇到换行符(包括在返回值中)、EOF 或者已经读取了length−1 字节后停止。如果没有指定

length,则默认为1KB,或者说1024 字节。出错时返回FALSE。

实例 5-6 一次读入一行数据

本实例演示了fgets 函数的应用,如代码5-8 所示。

【代码 5-8】 fgets.php

<?php

$handle = fopen ("hello/student.txt", "r");

while (!feof ($handle)) {

$buffer = fgets($handle,1024);

echo $buffer . "<br>";

}

fclose ($handle);

?>

fgets.php 文件的执行结果如图5-8 所示。

图 5-8 fgets.php 的执行结果

168 PHP 网络编程技术与实例

实例中使用代码循环读取了前面创建的 student.txt 文件中的数据。

提示 feof 函数为判断是否到了文件最后的函数,在后面会有详细介绍。

(2)fgetss 函数。fgetss 函数是fgets 函数的一个变体。其功能同fgets 函数基本类似,只

是fgetss 函数会过滤掉被读取内容中的HTML 和PHP 标记。

fgetss 函数的声明如下:

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

fgetss 函数和fgets()相同,只除了fgetss 尝试从读取的文本中去掉任何HTML 和PHP 标

记。可以用可选的第三个参数指定哪些标记不被去掉。当读取其他人写的文件的时候,可以

设置过滤一些恶意代码。因为一些恶意的HTML 和PHP 代码,可以很容易控制服务器。

实例 5-7 读取数据并过滤HTML 和PHP 标记

本实例演示了fgetss 函数的应用,如代码5-9 所示。

【代码 5-9】 fgetss.php

<?php

$filename = 'hello/3.txt';

$handle = fopen ($filename, "w");

fwrite($handle, "<b>i like dancing very much!</b>\r\n");

fwrite($handle, "<br>i like singing very much!\r\n");

fclose($handle);

echo "fgets 函数的输出结果:<br>";

$handle = fopen ("hello/3.txt", "r");

while (!feof ($handle)) {

$buffer = fgets($handle,1024); //fgets 函数,不过滤<b>、<br>等html 标记

echo $buffer;

}

fclose ($handle);

echo "<br><br>fgetss 函数的输出结果:<br>";

$handle = fopen ("hello/3.txt", "r");

while (!feof ($handle)) {

$buffer = fgetss($handle,1024); //fgetss 函数,过滤<b>、<br>等html 标记

echo $buffer;

}

fclose ($handle);

?>

fgetss.php 文件的执行结果如图5-9 所示。

图 5-9 fgetss.php 文件的执行结果

从图 5-9 中可以看出,由于fgets 函数没有过滤,因此,在显示的时候<b></b>将加粗显

第5 章 PHP 中的文件处理技术 169

示字体,而<br>标记将会换行。而用fgetss 函数则过滤了这几个html 标记,所以在浏览器中

的显示,没有将字体加粗,同时也没有换行。读者也可以右键单击浏览器,在弹出菜单中选

择【查看源文件】,可以看到两次输出的内容分别为:

//fgets 函数输出

<b>i like dancing very much!</b>

<br>i like singing very much!

//fgetss 函数输出

i like dancing very much!

i like singing very much!

(3)fgetcsv()函数。fgetcsv 函数也是fgets 函数的一个变体。该函数从文件指针中读入一

行并解析CVS 字段,该函数的声明如下:

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

和fgets()类似,只除了fgetcsv()解析读入的行并找出CVS 格式的字段然后返回一个包含

这些字段的数组。可选的第三个参数delimiter 的默认值是逗号。可选参数enclosure 的默认值

是双引号。delimiter 和enclosure 都被限制为一个字符。如果多于一个字符,则只使用第一个

字符。length 必须大于CVS 文件中长度最大的行(以便于处理行结束字符)。fgetcsv()出错时

返回FALSE,包括碰到文件结束时。

提示

CVS 文件中的空行将返回为一个包含有单个null 字段的数组,而不会被当

成错误。

如果在文件中使用了分隔符号,如逗号、制表符等,可以使用fgetcsv 函数将文件中读入

的一行分成多行。比如在appenddata.php 中,向student.txt 文件中写入了“$student1 = "姓名:

小狗\t 年龄:5\t 性别:男\r\n"”的记录,如果现在想将姓名、年龄以及性别分成三行显示,此时

可以通过分隔符“\t”来将该行分解成3 个字段,并保存在一个数组中。

实例 5-8 使用fgetcsv 函数解析CVS 文件

本实例介绍fgetcsv 函数的应用,代码5-10 所示。

【代码 5-10】 fgetcsv.php

<?php

$row = 1;

$handle = fopen ("hello/student.txt","r");

while ($data = fgetcsv ($handle, 1000, "\t")) {

$num = count ($data); //统计数组大小

print "<p> 在第 $row 行中有 $num 个字段: <br>\n";

$row++;

for ($c=0; $c < $num; $c++) {

print $data[$c] . "<br>\n";

}

}

fclose ($handle);

?>

fgetcsv.php 文件的执行结果如图5-10 所示。

从图 5-10 中可以看出,文件student.txt 中的每行文本,都通过分隔符“\t”分隔开,然

后分别输出。

170 PHP 网络编程技术与实例

图 5-10 fgetcsv.php 文件的执行结果

5.5.2 读取整个文件

前面介绍的3 个函数主要用于逐行读取文件中的数据,但是很多时候不需要逐行读取数

据,而是要一次读取整个文件的数据。PHP 中提供了4 个函数用于读取整个文件的数据。

(1)readfile()函数。readfile 函数的声明如下:

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

readfile 函数读入一个文件并写入到输出缓冲。该函数返回从文件中读入的字节数。如果

出错返回FALSE,并且除非是以@readfile()形式调用,否则会显示错误信息。

该函数首先打开目标文件,并且将文件的内容输出到标准输出,如浏览器中,然后关闭

该文件。使用该函数比较简单,不需要打开和关闭文件。

实例 5-9 读取整个文件

本实例使用readfile 函数读取整个文件的内容,如代码5-11 所示。

【代码 5-11】 readfile.php

<?php

readfile("hello/student.txt");

?>

代码5-11 比较简单,直接读取student.txt 文件中的数据,并显示在浏览器中,运行结果

如图5-11 所示。

图 5-11 readfile.php 文件执行结果

(2)fpassthru()函数。fpassthru 函数输出文件指针处的所有剩余数据,该函数的声明如下:

int fpassthru (resource handle)

该函数将给定的文件指针从当前的位置读取到EOF 并把结果写到输出缓冲区。如果发生

错误,fpassthru()返回FALSE。否则fpassthru()返回从handle 读取并传递到输出的字符数目。

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

用readfile(),这样可以省去fopen()调用。

第5 章 PHP 中的文件处理技术 171

提示

当在 Windows 系统中将fpassthru()用于二进制文件时,要确保在用fopen()

打开文件时在mode 中附加了“b”选项来将文件以二进制方式打开。建议在处

理二进制文件时使用“b”标志,这样可以使脚本的移植性更好。

同 readfile 相比,fpassthru 需要首先打开文件,数据读取完毕还需要关闭文件。另外

fpassthru 函数是读取当前指针之后的所有数据。假如当前指针已经在文件的中间,则只是输

出所有后面的数据。

实例 5-10 读取当前指针后的全部文件内容

本实例演示了如何通过fpassthru 函数读取当前指针后的全部内容,如代码5-12 所示。

【代码 5-12】 fpassthru.php

<?php

$filename = 'hello/student.txt';

$handle = fopen ($filename, "r");

$buffer = fgets ($handle,1024); //首先读取一行,移动指针

//接着调用fpassthru 输出剩下内容

fpassthru($handle);

fclose($handle);

?>

fpassthru.php 的执行结果如图5-12 所示。

图 5-12 fpassthru.php 文件执行结果

从图 5-12 可以看出,由于在代码中首先调用了fgets 函数读取了一行,因此接着调用

fpassthru 函数,只会输出接下来的两行内容(读者可以对比图5-11 和图5-12)。

实例 5-11 向浏览器发送图像

本实例用来向浏览器输出一幅图像,如代码5-13 所示。

【代码 5-13】 fpassthru_pic.php

<?php

$filename = 'hello/1.bmp';

$handle = fopen ($filename, "rb"); //二进制读取数据,使用rb 模式

//发送html 头,表示发送二进制数据

header("Content-Type: image/png");

//filesize 为获取文件大小,在后面介绍

header("Content-Length: ".filesize($filename));

//输出图像数据到浏览器

fpassthru($handle);

exit;

?>

172 PHP 网络编程技术与实例

fpassthru_pic.php 文件的执行结果如图5-13 所示。

图 5-13 fpassthru_pic.php

(3)file()函数。file 函数也是读取整个文件的内容,但是该函数会把整个文件读入一个

数组中。file 函数的声明如下:

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

和readfile()一样,只是file()将文件作为一个数组返回。数组中的每个单元都是文件中相

应的一行,包括换行符在内。如果失败,file()返回FALSE。如果想在include_path 中搜寻文

件,可以将可选参数use_include_path 设为“1”。

提示

返回的数组中每一行都包括了行结束符,因此,如果不需要行结束符,可以

使用trim()函数。

实例 5-12 将整个文件读入到数组

本实例使用file 函数将整个文件读入到数组并输出,如代码5-14 所示。

【代码 5-14】 file.php

<?php

// 将一个文件读入数组,这里读取的是远程文件

$lines = file ('http://www.sohu.com');

// 在数组中循环,显示html 的源文件并加上行号

foreach ($lines as $line_num => $line) {

echo "Line #<b>{$line_num}</b> : " . htmlspecialchars($line) . "<br>\n";

}

?>

file.php 文件的执行结果如图5-14 所示。

图 5-14 file.php 文件的执行结果

代码 5-14 通过函数file 打开sohu 网站的首页,然后将获取的内容按行编号输出。从代

码中很容易理解,file 函数是将整个文件的内容按行保存在了数组中。

第5 章 PHP 中的文件处理技术 173

(4)file_get_contents 函数。file_get_contents 函数将整个文件作为一个字符串读入。该函

数的声明如下:

string file_get_contents ( string filename [, int use_include_path [, resource

context]])

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

所指定的位置开始读取长度为maxlen 的内容。如果失败,file_get_contents()将返回FALSE。

如果操作系统支持还会使用内存映射技术来增强性能。除了file_get_contents()将文件返回为

一个字符串以外,其余与file()的使用一样。

提示 该函数适用于二进制对象。

实例 5-13 将整个文件读入到字符串

本实例使用file_get_contents 函数将文件读入到字符串,如代码5-15 所示。

【代码 5-15】 file_get_contents.php

<?php

// 将文件作为字符串读入到一个变量中

$lines = file_get_contents ('hello/student.txt');

//输出内容

echo $lines;

?>

file_get_contents.php 的执行结果如图5-15 所示。

图 5-15 file_get_contents.php 文件的执行结果

5.5.3 读取一个字符

很多时候需要对整个文件的每个字符进行分析,如查找、替换部分内容等。PHP 也提供

了相应的函数用来逐个读取数据。

(1)fgetc()函数。fgetc()函数从文件指针中读取字符,该函数的声明如下:

string fgetc (resource handle)

该函数返回包含有一个字符的字符串,该字符从handle 指向的文件中得到。碰到文件结

束即EOF 为真,否则返回FALSE。

实例 5-14 读入单个字符

本实例使用fgetc 函数读入文件中的单个字符,如代码5-16 所示。

【代码 5-16】 fgetc.php

<?php

$fp = fopen('hello/4.txt', 'r');

174 PHP 网络编程技术与实例

if (!$fp) {

echo '不能打开文件!';

}

while (false !== ($char = fgetc($fp))) {

echo "$char";

}

fclose($fp);

?>

fgetc.php 通过fgetc 函数逐个读取文件4.txt 中的字符。

注意

如果文件中包含有中文,则可能不能正确显示结果。因为一个中文字符包

含两个字节,而fgetc 通常只会读取一个字节的字符。

5.5.4 读取任意长度函数

另外一个读取文件的函数fread(),能够从文件中读取指定长度的数据。该函数的声明

如下:

string fread ( int handle, int length)

fread()从文件指针handle 读取最多length 个字节。该函数在读取完length 个字节数,或

到达EOF 的时候,或(对于网络流)当一个包可用时就会停止读取文件。同时该函数也能够

读取二进制文件。

实例 5-15 读入指定长度的字符串

本实例演示了fread 函数的应用,如代码5-17 所示。

【代码 5-17】 fread.php

<?php

$fp = fopen('hello/4.txt', 'r');

//读取文件的前10 个字符

$contents = fread($fp, 10);

echo $contents."<br><br>";

fclose($fp);

//读取网络数据包数据

$handle = fopen ("http://www.sohu.com/", "rb");

$contents = "";

do {

$data = fread($handle, 8192);

if (strlen($data) == 0) {

break;

}

$contents .= $data;

} while(true);

echo $contents;

fclose ($handle);

?>

第5 章 PHP 中的文件处理技术 175

fread.php 的运行结果如图5-16 所示。

图 5-16 fread.php 文件的执行结果

代码 5-17 首先从4.txt 文件读取了指定的10 个字符,然后打开远程文件下载数据。这里

打开的是搜狐的主页。

提示

上例比使用while(!feof())的方法性能要好,因为在每个循环中节约了函数

调用的花费。

5.5.5 文件定位

前面虽然介绍了逐行读取数据、逐个字符读取数据等,但是通过这些函数来定位文件指

针效率比较低。PHP 中有专门进行文件定位的函数。

(1)rewind()函数。rewind 函数将文件位置指针设为文件流的开头,其声明如下:

bool rewind ( resource handle)

如果成功则返回TRUE,失败则返回FALSE。文件指针必须合法,并且指向由fopen()

成功打开的文件。

提示

如果将文件以附加("a")模式打开,写入文件的任何数据总是会被附加在

后面,不管文件指针的位置。

实例 5-16 将文件指针指向文件头

本实例演示了rewind 函数的应用,如代码5-18 所示。

【代码 5-18】 rewind.php

<?php

$handle = fopen ("hello/student.txt", "r");

//首先读取第一行

$buffer = fgets($handle,1024);

echo $buffer . "<br>";

//读取第二行

$buffer = fgets($handle,1024);

echo $buffer . "<br>";

//将指针回到文件开始,继续读取一行数据,将读取到第一行数据

rewind($handle);

$buffer = fgets($handle,1024);

echo $buffer . "<br>";

fclose ($handle);

?>

rewind.php 的执行结果如图5-17 所示。

176 PHP 网络编程技术与实例

图 5-17 rewind.php 文件的执行结果

从图 5-18 可以看出,在使用rewind 函数之后,指针又回到了文件开始,所以最后一行

为文件的第一行数据。

(2)fseek()函数。fseek()函数用于文件指针定位,该函数的声明如下:

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

fseek 函数在文件中设定文件指针位置。新指针的位置,从文件头开始以字节数度量,是

在参数whence 指定的位置加上offset。

whence 的值定义如下。

SEEK_SET:设定位置等于offset 字节。

SEEK_CUR:设定位置为当前位置加上offset。

SEEK_END:设定位置为文件尾加上offset(要移动到文件尾之前的位置,需要给offset

传递一个负值)。

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

如果函数调用成功则返回 0;否则返回−1。

注意 移动到 EOF 之后的位置不算错误。

实例 5-17 设定文件指针位置

本实例演示了fseek 函数的应用,如代码5-19 所示。

【代码 5-19】 fseek.php

<?php

$handle = fopen ("hello/5.txt", "r");

//首先读取第一行,读取完毕后,指针在第一行最后

$buffer = fgets($handle,1024);

echo $buffer . "<br>";

//接着将指针向后移动5 个字节,因为是相对当前位置,所以需要设定SEEK_CUR 参数

fseek($handle,5,SEEK_CUR);

//接着读取一行

$buffer = fgets($handle,1024);

echo $buffer . "<br>";

//将指针回到文件开始,重新读取第一行,因为是绝对位置为0,

//则不用设置whence 参数默,默认的whence 是SEEK_SET,表示绝对位置

fseek($handle,0);

//读取一行数据,因为指针回到文件开始,所以会读取第一行数据

$buffer = fgets($handle,1024);

echo $buffer . "<br>";

fclose ($handle);

?>

fseek.php 文件的执行结果如图5-18 所示。

第5 章 PHP 中的文件处理技术 177

图 5-18 fseek.php 文件的执行结果

代码 5-19 打开了文件5.txt,然后先读取第一行数据,接着将指针向后移动5,读取第二

行中第5 个字符后面剩下的字符。然后将指针设置为文件开始,并获取一行数据。

5.txt 的文件内容如下所示:

1.I woke up this morning with a buzz rollin' 'round in my brain

2.I haven't been drinkin' but it feels pretty good just the same

3.It must be contagious-looks like it's goin' around

从上面可以看出,rewind 函数等于一个0 偏移量的fseek 函数。

(3)ftell()函数。ftell 函数并不起实际的定位作用,而是报告当前文件指针的位置。该函

数的声明如下:

int ftell(resource handle)

返回由handle 指定的文件指针的位置,即文件流中的偏移量。如果出错,返回FALSE。

实例 5-18 获取文件指针位置

本实例演示了ftell 函数的应用,如代码5-20 所示。

【代码 5-20】 ftell.php

<?php

// 打开文件并读些数据

$fp = fopen("hello/5.txt", "r");

//获得前15 个字符

$data = fgets($fp, 15);

// 获取当前指针

echo ftell($fp); // 输出当前位置

fclose($fp);

?>

代码5-20 的输出结果为14,因为之前已经获取了15 个字符,而指针从0 开始计算,所

以当前位置为14。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: