距离上一次更新PHP又过了很久……太多东西要学了。这次更新主要是因为遇到了新的需求,要用PHP开发一个平台后端,不得不再捡起来……

总之,继续启动!


这章我们主要粗略的过一遍PHP的数据储存和读取,节奏会比较快。之所以快马加鞭,是因为PHP的精髓不在这里。本章只涉及最基本的读取文件操作,大部分和C语言类似,而且目前储存数据更常用的是采取DBMS数据库来管理数据储存。所以本章只做简单的归纳,快速掌握就行。

文件处理

PHP的处理文件方式和C语言大致相同,都分为三步:

  1. 打开文件。如果文件不存在就创建(写模式)或者报错/退出(读模式)
  2. 从文件中读取/写入数据
  3. 关闭文件

接下来我们先从打开文件开始介绍,主要讲解一下函数。

打开文件

在PHP中打开文件,一般使用fopen()函数。除了传递需要打开的文件名外,还需要指定文件模式。

fopen()

上文中提到的文件模式,主要有三点需要注意:

  1. 只读/只写或者读/写
  2. 如果选择写模式,是覆盖原内容还是追加
  3. 可以使用二进制模式处理文件

fopen支持上述三种模式,使用方法为fopen(file_path,file_mode,[include_path,protocol])。文件路径和文件模式是必选的,使用方法和C相同。主要参数如下,b表示二进制读/写。

  • r,rb读文件
  • w,wb写文件
  • a,ab追加写文件

后两者是可选的,include_path是一个布尔值,PHP根据它判断是否要搜索include_path,这个值在PHP的配置中设置;后者则是协议前缀,比如http://

通过FTP或者HTTP打开文件

除了打开一个本地文件进行操作外,fopen()函数还支持通过FTP、HTTP等协议打开其他文件,这点可以在php.ini文件中设置。如果文件名以http://开头,则fopen()函数将建立一个到指定服务器的连接,并返回一个指向HTTP响应的指针。FTP情况同理。

错误抑制符

调用fopen()函数时可能会产生各种错误,比如权限不够无法读取文件,或者文件不存在。可以在调用fopen()函数前加上@错误抑制符来阻止PHP报错并用if语句来设置一个对用户更友好的自定义报错信息。

@$fp=fopen("order.txt","ab");
if (!$fp){
...
}

readfile()

向函数传递文件名,这个函数会把文件中所有的内容读取并输出至标准输出(浏览器)上,然后再关闭这个文件。

fpassthru()

像这个函数传递文件指针,其余作用和readfile()函数相同。

file()

file()函数和readfile()函数用法和效果相同,除此之外它还会把读取到的文件数据作为返回值发送到一个数组里。其中每一行都对应数组的一个元素。

file_get_contents()

作用与readfile()函数相同,但是这个函数不会把文件内容回显到浏览器上,而是以字符串的形式返回。

fread()

向函数传递一个文件指针和一个长度,函数将读取指定长度或者网络数据包结束前的部分。

写文件

在PHP中有很多写入文件的函数,下面一一列举。

fwrite()/fputs()

fwrite的使用方法为fwrite($fp,$outputstring);,要求传入一个文件指针并将保存在$outputstring的字符串写入文件。fputs()是fwrite()函数的别名。

file_put_contents

该函数原型如下所示。

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

它不需要使用fopen函数打开文件就可以将包含在data中的字符串写入到文件中。与之相匹配的函数是file_get_contents()。

fgets()

传入一个文件指针,每次读入一行,直到读取到换行符\n或者文件结束符EOF结束。

fgetss()

fgets()函数的变体,更加安全。它会把读取到的文件中所有的PHP和HTML标记符过滤。这样可以防止自己的HTML代码被破坏格式,或者读取到恶意的PHP代码。

fgetcsv()

fgets()函数的另一个变体,向函数传入文件指针,读取长度和分隔符。函数会在读取到分隔符时自动换行,分隔符可以是制表符\t,空格等。如果不希望限制读取长度,可以将此参数设置为0。

fgetc()

传入一个文件指针,一次读取一个字符

文件锁定

之所以引入这个概念,是因为PHP会遇到与C语言中不一样的情况。假如在一个订单系统中有两位用户同时下单了最后一个商品,如果没有文件锁定就会导致紊乱。所以引入flock()函数,在一个用户打开文件进行操作时,其他用户无法对该文件进行操作。

flock()

在任何一个文件被打开且在进行读写前,应该使用这个函数进行锁定。函数原型如下。

bool flock(resource fp,int operation[,int&wouldblock])

除了传入文件指针外,一样的要指定锁定模式。第三个参数是可选的,如果文件锁定导致进程堵塞,那么第三个参数的值将为true。

其中锁定模式总结如下。

操作值 意义
LOCK_SH 读操作锁定。意味着文件可以共享,其他人可以读文件
LOCK_EX 写操作锁定。代表互斥,文件不能共享
LOCK_UN 释放锁定
LOCK_NB 防止在请求加锁时发生阻塞(Windows系统不支持)(我也不知道这是什么鬼)

如果要使用flock()函数,就必须将其添加到所有使用文件的脚本中,否则没有意义。

使用flock()函数后,代码更加健壮,但是还不够好。因为加锁时仍然会产生竞争条件,这时候我们就需要DBMS数据库管理系统来帮助我们解决这个问题,后面再慢慢讲。

关闭文件

fclose()

和C语言相同,向其传入一个文件指针,关闭成功返回true,否则返回false。

其他

feof()

判断一个文件是否读到文件结尾。

file_exist()

判断一个文件是否存在。

filesize()

查看一个文件的大小,单位为字节。

删除一个文件。

rewind()、fseek()、ftell()

用于在文件中定位,用法和C语言相同,不多赘述(无论是PHP还是C语言用的都极少)。

300483