PHP实现读取一个1G的文件大小


Posted in PHP onAugust 24, 2013

需求如下: 现有一个1G左右的日志文件,大约有500多万行, 用php返回最后几行的内容。

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

下面是一段用file来取出这具文件最后一行的代码.

ini_set('memory_limit','-1');
$file = 'access.log';
$data = file($file);
$line = $data[count($data)-1];2.直接调用linux的tail命令来显示最后几行

在linux命令行下,可以直接使用tail -n 10 access.log很轻易的显示日志文件最后几行,可以直接用php来调用tail命令,执行php代码如下.
file = 'access.log';
$file = escapeshellarg($file); // 对命令行参数进行安全转义
$line = `tail -n 1 $file`;
echo $line;3. 直接使用php的fseek来进行文件操作

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

方法一:
首先通过fseek找到文件的最后一位EOF,然后找最后一行的起始位置,取这一行的数据,再找次一行的起始位置,再取这一行的位置,依次类推,直到找到了$num行。

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行数据.

实现代码如下

$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方法三:
$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;
PHP 相关文章推荐
用ADODB来让PHP操作ACCESS数据库的方法
Dec 31 PHP
15种PHP Encoder的比较
Apr 17 PHP
php heredoc和phpwind的模板技术使用方法小结
Mar 28 PHP
在php MYSQL中插入当前时间
Apr 06 PHP
php小偷相关截取函数备忘
Nov 28 PHP
php继承的一个应用
Sep 06 PHP
解析在zend Farmework下如何创立一个FORM表单
Jun 28 PHP
php json_encode值中大括号与花括号区别
Sep 30 PHP
PHP中对各种加密算法、Hash算法的速度测试对比代码
Jul 08 PHP
php实现数组中索引关联数据转换成json对象的方法
Jul 08 PHP
php实现图片上传并进行替换操作
Mar 15 PHP
PHP实现求解最长公共子串问题的方法
Nov 17 PHP
一致性哈希算法以及其PHP实现详细解析
Aug 24 #PHP
PHP如何利用P3P实现跨域
Aug 24 #PHP
PHP引用符&amp;的用法详细解析
Aug 22 #PHP
新手菜鸟必读:session与cookie的区别
Aug 22 #PHP
PHP mysql与mysqli事务使用说明 分享
Aug 17 #PHP
php中url传递中文字符,特殊危险字符的解决方法
Aug 17 #PHP
测试PHP连接MYSQL成功与否的代码
Aug 16 #PHP
You might like
人族 Terran 魔法与科技
2020/03/14 星际争霸
php数组函数序列之each() - 获取数组当前内部指针所指向元素的键名和键值,并将指针移到下一位
2011/10/31 PHP
php自动加载机制的深入分析
2013/06/08 PHP
php获取用户浏览器版本的方法
2015/01/03 PHP
jquery ajax执行后台方法
2010/03/18 Javascript
基于Jquery与WebMethod投票功能实现代码
2011/01/19 Javascript
使用javascript获取flash加载的百分比的实现代码
2011/05/25 Javascript
JavaScript检查数字是否为整数或浮点数的方法
2015/06/09 Javascript
如何用JS判断两个数字的大小
2016/07/21 Javascript
jQuery实现最简单的切换图效果【可兼容IE6、火狐、谷歌、opera等】
2016/09/04 Javascript
Vue响应式添加、修改数组和对象的值
2017/03/20 Javascript
angular json对象push到数组中的方法
2018/02/27 Javascript
详解微信小程序之提高应用速度小技巧
2020/01/07 Javascript
基于better-scroll 实现歌词联动功能的代码
2020/05/07 Javascript
element-ui 实现响应式导航栏的示例代码
2020/05/08 Javascript
JS如何判断对象是否包含某个属性
2020/08/29 Javascript
搭建vscode+vue环境的详细教程
2020/08/31 Javascript
Openlayers实现地图的基本操作
2020/09/28 Javascript
在Python中操作日期和时间之gmtime()方法的使用
2015/05/22 Python
Python调用SQLPlus来操作和解析Oracle数据库的方法
2016/04/09 Python
基于numpy中数组元素的切片复制方法
2018/11/15 Python
Python3实现的简单工资管理系统示例
2019/03/12 Python
python读取tif图片时保留其16bit的编码格式实例
2020/01/13 Python
python爬取王者荣耀全皮肤的简单实现代码
2020/01/31 Python
解决Python 异常TypeError: cannot concatenate 'str' and 'int' objects
2020/04/08 Python
实现ECharts双Y轴左右刻度线一致的例子
2020/05/16 Python
通过cmd进入python的步骤
2020/06/16 Python
python利用线程实现多任务
2020/09/18 Python
Farnell德国:电子元器件供应商
2018/07/10 全球购物
迟到检讨书大全
2014/01/25 职场文书
《她是我的朋友》教学反思
2014/04/26 职场文书
敲诈同学钱财检讨书范文
2014/11/18 职场文书
搞笑老公保证书
2015/02/26 职场文书
职工培训工作总结
2015/08/10 职场文书
MySQL脏读,幻读和不可重复读
2022/05/11 MySQL
Nginx跨域问题解析与解决
2022/08/05 Servers