php对大文件进行读取操作的实现代码


Posted in PHP onJanuary 23, 2013

在php中,对于文件的读取时,最快捷的方式莫过于使用一些诸如file、file_get_contents之类的函数,简简单单的几行代码就能很漂亮的完成我们所需要的功能。但当所操作的文件是一个比较大的文件时,这些函数可能就显的力不从心, 下面将从一个需求入手来说明对于读取大文件时,常用的操作方法。
需求

有一个800M的日志文件,大约有500多万行, 用php返回最后几行的内容。

实现方法

1. 直接采用file函数来操作

注:由于 file函数是一次性将所有内容读入内存,而php为了防止一些写的比较糟糕的程序占用太多的内存而导致系统内存不足,使服务器出现宕机,所以默认情况下限制只能最大使用内存16M,这是通过php.ini里的memory_limit = 16M来进行设置,这个值如果设置-1,则内存使用量不受限制.

下面是一段用file来取出这具文件最后一行的代码.
整个代码执行完成耗时 116.9613 (s).

$fp = fopen($file, "r"); 
$num = 10; 
$chunk = 4096; 
$fs = sprintf("%u", filesize($file)); 
$max = (intval($fs) == PHP_INT_MAX) ? PHP_INT_MAX : filesize($file); 
for ($len = 0; $len < $max; $len += $chunk) { 
$seekSize = ($max - $len > $chunk) ? $chunk : $max - $len; 
fseek($fp, ($len + $seekSize) * -1, SEEK_END); 
$readData = fread($fp, $seekSize) . $readData; if (substr_count($readData, "\n") >= $num + 1) { 
preg_match("!(.*?\n){".($num)."}$!", $readData, $match); 
$data = $match[0]; 
break; 
} 
} 
fclose($fp); 
echo $data;

我机器是2个G的内存,当按下F5运行时,系统直接变灰,差不多20分钟后才恢复过来,可见将这么大的文件全部直接读入内存,后果是多少严重,所以不在万不得以,memory_limit这东西不能调得太高,否则只有打电话给机房,让reset机器了.

2.直接调用linux的tail命令来显示最后几行

在linux命令行下,可以直接使用tail -n 10 access.log很轻易的显示日志文件最后几行,可以直接用php来调用tail命令,执行php代码如下.
整个代码执行完成耗时 0.0034 (s)

file = 'access.log'; 
$file = escapeshellarg($file); // 对命令行参数进行安全转义 
$line = `tail -n 1 $file`; 
echo $line;

3. 直接使用php的fseek来进行文件操作

这种方式是最为普遍的方式,它不需要将文件的内容全部读入内容,而是直接通过指针来操作,所以效率是相当高效的.在使用fseek来对文件进行操作时,也有多种不同的方法,效率可能也是略有差别的,下面是常用的两种方法.

方法一
首先通过fseek找到文件的最后一位EOF,然后找最后一行的起始位置,取这一行的数据,再找次一行的起始位置,再取这一行的位置,依次类推,直到找到了$num行。
实现代码如下
整个代码执行完成耗时 0.0095 (s)

function tail($fp,$n,$base=5) 
{ 
assert($n>0); 
$pos = $n+1; 
$lines = array(); 
while(count($lines)< =$n){ 
try{ 
fseek($fp,-$pos,SEEK_END); 
} catch (Exception $e){ 
fseek(0); 
break; 
} 
$pos *= $base; 
while(!feof($fp)){ 
array_unshift($lines,fgets($fp)); 
} 
} 
return array_slice($lines,0,$n); 
} 
var_dump(tail(fopen("access.log","r+"),10));

方法二
还是采用fseek的方式从文件最后开始读,但这时不是一位一位的读,而是一块一块的读,每读一块数据时,就将读取后的数据放在一个buf里,然后通过换行符(\n)的个数来判断是否已经读完最后$num行数据.
实现代码如下
整个代码执行完成耗时 0.0009(s).
$fp = fopen($file, "r"); 
$line = 10; 
$pos = -2; 
$t = " "; 
$data = ""; 
while ($line > 0) { 
while ($t != "\n") { 
fseek($fp, $pos, SEEK_END); 
$t = fgetc($fp); 
$pos --; 
} 
$t = " "; 
$data .= fgets($fp); 
$line --; 
} 
fclose ($fp); 
echo $data

方法三
整个代码执行完成耗时 0.0003(s)
ini_set('memory_limit','-1'); 
$file = 'access.log'; 
$data = file($file); 
$line = $data[count($data)-1]; 
echo $line;
PHP 相关文章推荐
超级好用的一个php上传图片类(随机名,缩略图,加水印)
Jun 30 PHP
如何使用PHP批量去除文件UTF8 BOM信息
Aug 05 PHP
JoshChen_web格式编码UTF8-无BOM的小细节分析
Aug 16 PHP
PHP使用SOAP调用.net的WebService数据
Nov 12 PHP
PHP内存缓存Memcached类实例
Dec 08 PHP
Zend Framework教程之Application用法实例详解
Mar 14 PHP
php实现搜索类封装示例
Mar 31 PHP
PHP编写daemon process 实例详解
Nov 13 PHP
小程序微信支付功能配置方法示例详解【基于thinkPHP】
May 05 PHP
PHP中的self关键字详解
Jun 23 PHP
laravel框架使用FormRequest进行表单验证,验证异常返回JSON操作示例
Feb 18 PHP
thinkphp5.1 框架钩子和行为用法实例分析
May 25 PHP
php删除与复制文件夹及其文件夹下所有文件的实现代码
Jan 23 #PHP
php删除文件夹及其文件夹下所有文件的函数代码
Jan 23 #PHP
php定时删除文件夹下文件(清理缓存文件)
Jan 23 #PHP
PHP关联数组的10个操作技巧
Jan 21 #PHP
用PHP即时捕捉PHP中的错误并发送email通知的实现代码
Jan 19 #PHP
PHP中CURL方法curl_setopt()函数的参数分享
Jan 19 #PHP
php牛逼的面试题分享
Jan 18 #PHP
You might like
收音机鉴频器对声音的影响和频偏分析
2021/03/02 无线电
PHP中将数组转成XML格式的实现代码
2011/08/08 PHP
PHP/HTML混写的四种方式总结
2017/02/27 PHP
PDO::exec讲解
2019/01/28 PHP
PHP Beanstalkd消息队列的安装与使用方法实例详解
2020/02/21 PHP
学习ExtJS accordion布局
2009/10/08 Javascript
调用DOM对象的focus使文本框获得焦点
2014/02/19 Javascript
JS实现图片的不间断连续滚动的简单实例
2016/06/03 Javascript
很实用的js选项卡切换效果
2016/08/12 Javascript
几种二级联动案例(jQuery\Array\Ajax php)
2016/08/13 Javascript
canvas的神奇用法
2017/02/03 Javascript
几行js代码实现自适应
2017/02/24 Javascript
jQuery实现上传图片前预览效果功能
2017/08/03 jQuery
解决Vue.js父组件$on无法监听子组件$emit触发事件的问题
2018/09/12 Javascript
Django+vue跨域问题解决的详细步骤
2019/01/20 Javascript
原生js实现随机点餐效果
2019/12/10 Javascript
js实现拖拽元素选择和删除
2020/08/25 Javascript
Vue+Bootstrap收藏(点赞)功能逻辑与具体实现
2020/10/22 Javascript
[11:42]2018DOTA2国际邀请赛寻真——OG卷土重来
2018/08/17 DOTA
Python微信库:itchat的用法详解
2017/08/14 Python
[原创]python爬虫(入门教程、视频教程)
2018/01/08 Python
Python 将Matrix、Dict保存到文件的方法
2018/10/30 Python
Django如何实现上传图片功能
2019/08/16 Python
python操作cfg配置文件方式
2019/12/22 Python
TensorFlow实现checkpoint文件转换为pb文件
2020/02/10 Python
Django实现celery定时任务过程解析
2020/04/21 Python
python向企业微信发送文字和图片消息的示例
2020/09/28 Python
巴基斯坦电子产品购物网站:Home Shopping
2017/09/14 全球购物
Intimissimi德国网上商店:意大利知名内衣品牌
2018/04/03 全球购物
NYX Professional Makeup英国官网:美国平价专业彩妆品牌
2019/11/13 全球购物
VICHY薇姿俄罗斯官方网上商店:法国护肤品牌,火山温泉水
2019/11/22 全球购物
员工拓展培训方案
2014/02/15 职场文书
关爱残疾人演讲稿
2014/05/24 职场文书
党员干部三严三实心得体会
2014/10/13 职场文书
三傻大闹宝莱坞观后感
2015/06/03 职场文书
vue3不同环境下实现配置代理
2022/05/25 Vue.js