PHP Cookbook读书笔记 – 第23章文件
概述
文件是在web应用中经常会碰到的一个部分,本章主要包括如何在PHP中打开、关闭和操纵文件,以及在打开文件后能够对文件做哪些处理等内容。
创建或打开一个本地文件
可以用fopen()函数打开/创建一个本地文件
<?php $fh = fopen('file.txt','rb') or die("can't open file.txt: $php_errormsg"); ?>
fopen函数的第二个参数指定了打开该流的访问类型:
模式 | 可读? | 可写? | 文件指针 | 截断? | 创建? | 说明 |
---|---|---|---|---|---|---|
r | 是 | 否 | 开始 | 否 | 否 | 只读打开 |
r+ | 是 | 是 | 开始 | 否 | 否 | 读写方式打开 |
w | 否 | 是 | 开始 | 是 | 是 | 写入方式打开 |
w+ | 是 | 是 | 开始 | 是 | 是 | 读写方式打开 |
a | 否 | 是 | 结尾 | 否 | 是 | 写入方式打开,追加 |
a+ | 是 | 是 | 结尾 | 否 | 是 | 读写方式打开,追加 |
x | 否 | 是 | 开始 | 否 | 是 | 写入方式打开,如果文件存在返回false,并产生一个警告信息 |
x+ | 是 | 是 | 开始 | 否 | 是 | 创建并以读写方式打开,同上存在返回false,并产生一个警告信息 |
文件操作需要考虑其操作系统,在不同的操作系统下的某些文件操作是不一样的,例如:在Unix系统中新行用\n,Windows中是\r\n,而Macintosh中则是\r。
除上面这些外,还有b表示以二进制方式打开文件(默认是ASCII形式),以二进制形式打开文件可以在不同操作系统中具有很好的移植性,故官方手册中强烈建议使用二进制模式打开文件。
另外windows下还提供了一个t用来透明转换\n为\r\n。官方有一次强烈建议为移植性考虑,重写那些依赖于t模式的代码,改为正确的结束符并改成b模式
打开远程文件
打开远程文件也可以用fopen()函数,操作方法和本地文件差不多,但有需要注意的一点是操纵远程文件需要php.ini中的allow_url_fopen设置为on。下面分别列举了打开ftp和http打开一个远程txt文件:
<?php $fh = fopen('ftp://username:password@ftp.example.com/pub/Index','r'); $fh = fopen('http://username:password@www.example.com/robots.txt','r'); ?>
读取整个文件内容到字符串
使用file_get_contents()方法可以一次将一整个文件的内容加载到一个变量中去。但如果是要将整个文件内容输出可以选择fpassthru()或者readfile()函数。(对于图片文件的显示等也适用)
按行读取文件
可以使用fgets()函数按行读取文件
$lines = 0; if ($fh = fopen('orders.txt','r')) { while (! feof($fh)) { if (fgets($fh)) { $lines++; } } fclose($fh); } print $lines;
按指定字节数读取文件
可以使用fread()函数按指定字节数读取文件
$handle = fopen ("http://www.example.com/", "rb"); $contents = ""; while (!feof($handle)) { $contents .= fread($handle, 1024); } fclose($handle);
例子中每次按1M字节大小读取文件远程文件
随机化处理文件中的所有行
$lines = file('quotes-of-the-day.txt'); $lines = shuffle($lines);
读取配置文件
可以用parse_ini_file()函数来读取类似php.ini格式的文件,例如
<?php $config = parse_ini_file('/etc/example.ini'); ?>
example.ini配置文件内容如下:
; PHYSICAL FEATURES eyes=brown hair=brown glasses=yes ; OTHER FEATURES name=Susannah likes=monkeys,ice cream,reading
返回的数组如下
<?php Array ( [eyes] => brown [hair] => brown [glasses] => 1 [name] => Susannah [likes] => monkeys,ice cream,reading ) ?>
如果给parse_ini_file()增加个参数,将得到不同的结果数组
<?php $config = parse_ini_file('/etc/example.ini',1); ?>
得到的$conf如下:
Array ( [physical] => Array ( [eyes] => brown [hair] => brown [glasses] => 1 ) [other] => Array ( [name] => Susannah [likes] => monkeys,ice cream,reading ) )
不通过临时文件来修改文件
通过file_get_contents()来读取文件内容,修改后,通过file_put_contents()函数回写到文件中去
$contents = file_get_contents('pickles.txt'); $contents = strtoupper($contents); file_put_contents('pickles.txt', $contents);
同时写入到多个文件句柄
function pc_multi_fwrite($fhs,$s,$length=NULL) { if (is_array($fhs)) { if (is_null($length)) { foreach($fhs as $fh) { fwrite($fh,$s); } } else { foreach($fhs as $fh) { fwrite($fh,$s,$length); } } } } $fhs['file'] = fopen('log.txt','w') or die($php_errormsg); $fhs['screen'] = fopen('php://stdout','w') or die($php_errormsg); pc_multi_fwrite($fhs,'The space shuttle has landed.');
调用shell命令
如果想通过PHP调用shell命令并获取输出可以通过popen()函数实现,代码如下:
$ph = popen('/sbin/route','r') or die($php_errormsg); while (! feof($ph)) { $s = fgets($ph) or die($php_errormsg); } pclose($ph) or die($php_errormsg);
锁定文件
通过flock()对文件执行劝告式锁定,可选择排他锁或共享锁,排他锁意味着每次只能由一个进程控制。共享锁意味着文件每次可能由多个进程控制。根据其特性可知,在写入文件之前应使用排他锁,在读取文件前应使用共享锁。
读写压缩文件
使用compress.zlib或compress.bzip2扩展流封装程序和标准文件函数可以读写gzip或zip文件。
//读取本地的gzip文件 $fh = fopen('compress.zlib://lots-of-data.gz','r') or die("can't open: $php_errormsg"); while ($line = fgets($fh)) { // $line is the next line of uncompressed data } fclose($fh) or die("can't close: $php_errormsg"); //读取远程的bzip2压缩文件 $fp = fopen('http://www.example.com/something-compressed.bz2','r'); stream_filter_append($fp, 'bzip2.uncompress'); while (! feof($fp)) { $data = fread($fp); // do something with $data; } fclose($fp);