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 相关文章推荐
关于文本留言本的分页代码
Oct 09 PHP
繁体中文转换为简体中文的PHP函数
Oct 09 PHP
php str_replace的替换漏洞
Mar 15 PHP
php explode函数实例代码
Feb 27 PHP
PHP仿博客园 个人博客(1) 数据库与界面设计
Jul 05 PHP
解析php开发中的中文编码问题
Aug 08 PHP
destoon会员注册提示“数据校验失败(2)”解决方法
Jun 21 PHP
thinkphp配置连接数据库技巧
Dec 02 PHP
浅谈PDO的rowCount函数
Jun 18 PHP
PHP基于递归实现的约瑟夫环算法示例
Aug 27 PHP
PHP面向对象程序设计之接口的继承定义与用法详解
Dec 20 PHP
phpstudy隐藏index.php的方法
Sep 21 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
PHP中判断变量为空的几种方法分享
2013/08/26 PHP
用PHP和Shell写Hadoop的MapReduce程序
2014/04/15 PHP
php实现的微信红包算法分析(非官方)
2015/09/25 PHP
url 特殊字符 传递参数解决方法
2010/01/01 Javascript
用js实现的自定义的对话框的实现代码
2010/03/21 Javascript
jQuery中after的两种用法实例
2013/07/03 Javascript
jqGrid读取选择的多行的某个属性代码
2014/05/18 Javascript
javascript 控制input只允许输入的各种指定内容
2014/06/19 Javascript
JavaScript中字符串拼接的基本方法
2015/07/07 Javascript
详细解读JavaScript编程中的Promise使用
2015/07/27 Javascript
JS及JQuery对Html内容编码,Html转义
2017/02/17 Javascript
vue实现通讯录功能
2018/07/14 Javascript
JS中DOM元素的attribute与property属性示例详解
2018/09/04 Javascript
node中使用es6/7/8(支持性与性能)
2019/03/28 Javascript
vue 解决路由只变化参数页面组件不更新问题
2019/11/05 Javascript
详解Vue的组件中data选项为什么必须是函数
2020/08/17 Javascript
javascript实现雪花飘落效果
2020/08/19 Javascript
简述Python中的进程、线程、协程
2016/03/18 Python
Python 列表理解及使用方法
2017/10/27 Python
Pandas DataFrame 取一行数据会得到Series的方法
2018/11/10 Python
Python实例方法、类方法、静态方法的区别与作用详解
2019/03/25 Python
python单线程下实现多个socket并发过程详解
2019/07/27 Python
tensorflow实现读取模型中保存的值 tf.train.NewCheckpointReader
2020/02/10 Python
解决pytorch多GPU训练保存的模型,在单GPU环境下加载出错问题
2020/06/23 Python
安装并免费使用Pycharm专业版(学生/教师)
2020/09/24 Python
美国二手奢侈品寄售网站:TheRealReal
2016/10/29 全球购物
anello泰国官方网站:日本流行包包品牌
2019/08/08 全球购物
什么是事务?为什么需要事务?
2012/01/09 面试题
国际贸易实训报告
2014/11/05 职场文书
社区服务活动感想
2015/08/11 职场文书
2016国庆节67周年寄语
2015/12/07 职场文书
2019年励志签名:致拼搏路上的自己
2019/10/11 职场文书
html+css 实现简易导航栏功能
2021/04/07 HTML / CSS
pycharm 如何查看某一函数源码的快捷键
2021/05/12 Python
Python一行代码实现自动发邮件功能
2021/05/30 Python
python使用torch随机初始化参数
2022/03/22 Python