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 相关文章推荐
substr()函数中文版
Oct 09 PHP
Php做的端口嗅探器--可以指定网站和端口
Oct 09 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(二)
Jun 23 PHP
重新认识php array_merge函数
Aug 31 PHP
PHP随机生成唯一HASH值自定义函数
Apr 20 PHP
PHP 设计模式系列之 specification规格模式
Jan 10 PHP
PHP学习笔记之php文件操作
Jun 03 PHP
CI框架使用composer安装的依赖包步骤与方法分析
Nov 21 PHP
可兼容php5与php7的cURL文件上传功能实例分析
May 11 PHP
PHP实现登录验证码校验功能
May 17 PHP
PHP进阶学习之Geo的地图定位算法详解
Jun 19 PHP
Laravel基础-关于引入公共文件的两种方式
Oct 18 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
Syphon 虹吸式咖啡壶冲煮–拨动法
2021/03/03 冲泡冲煮
php array_flip() 删除数组重复元素
2009/01/14 PHP
php编程每天必学之表单验证
2016/03/01 PHP
thinkPHP+ajax实现统计页面pv浏览量的方法
2017/03/15 PHP
jquery自动完成插件(autocomplete)应用之PHP版
2009/12/15 Javascript
jQuery解决iframe高度自适应代码
2009/12/20 Javascript
JQuery Tab选项卡效果代码改进版
2010/04/01 Javascript
jquery中dom操作和事件的实例学习 下拉框应用
2011/12/01 Javascript
jquery sortable的拖动方法示例详解
2014/01/16 Javascript
基于insertBefore制作简单的循环插空效果
2015/09/21 Javascript
AngularJS入门教程引导程序
2016/08/18 Javascript
vue页面跳转后返回原页面初始位置方法
2018/02/11 Javascript
Vue打包后出现一些map文件的解决方法
2018/02/13 Javascript
node内置调试方法总结
2018/02/22 Javascript
vue+webpack实现异步加载三种用法示例详解
2018/04/24 Javascript
[19:24]DOTA2客户端使用指南 一分钟快速设置轻松超神
2013/09/24 DOTA
Python随机生成一个6位的验证码代码分享
2015/03/24 Python
Python求导数的方法
2015/05/09 Python
Python外星人入侵游戏编程完整版
2020/03/30 Python
Python numpy 提取矩阵的某一行或某一列的实例
2018/04/03 Python
python中实现将多个print输出合成一个数组
2018/04/19 Python
Python3.6基于正则实现的计算器示例【无优化简单注释版】
2018/06/14 Python
使用python对文件中的数值进行累加的实例
2018/11/28 Python
Python中断多重循环的思路总结
2019/10/04 Python
Groupon西班牙官方网站:在线优惠券和交易,节省高达70%
2021/03/13 全球购物
用Python写一个for循环的例子
2016/07/19 面试题
成人毕业生自我鉴定
2013/10/18 职场文书
教研活动总结
2014/04/28 职场文书
文明礼仪伴我行演讲稿
2014/05/12 职场文书
工程售后服务承诺书
2014/05/21 职场文书
施工安全责任书范本
2014/07/24 职场文书
公司的门卫岗位职责
2014/09/09 职场文书
道歉信怎么写
2015/05/12 职场文书
一年之计:2019年下半年的计划
2019/05/07 职场文书
python如何利用traceback获取详细的异常信息
2021/06/05 Python
Win11 25163.1010更新补丁KB5016904推送,测试服务验证管道(附更新修复汇总)
2022/07/23 数码科技