php使用file函数、fseek函数读取大文件效率对比分析


Posted in PHP onNovember 04, 2016

php读取大文件可以使用file函数和fseek函数,但是二者之间效率可能存在差异,本文章向大家介绍php file函数与fseek函数实现大文件读取效率对比分析,需要的朋友可以参考一下。

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

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

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

<?php
  ini_set('memory_limit', '-1');
  $file = 'access.log';
  $data = file($file);
  $line = $data[count($data) - 1];
  echo $line;
  ?>

整个代码执行完成耗时 116.9613 (s)。

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

2.直接使用PHP的 fseek 来进行文件操作

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

方法一

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

实现代码如下

<?php
  $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--;
    }// http://www.manongjc.com
    $t = " ";
    $data .= fgets($fp);
    $line--;
  }
  fclose($fp);
  echo $data
  ?>

整个代码执行完成耗时 0.0095 (s) 

方法二

还是采用fseek的方式从文件最后开始读,但这时不是一位一位的读,而是一块一块的读,每读一块数据时,就将读取后的数据放在一个buf里,然后通过换 行符(\n)的个数来判断是否已经读完最后$num行数据。

实现代码如下

<?php
  $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)
    {
      // 作者:码农教程  http://www.manongjc.com
      preg_match("!(.*?\n){" . ($num) . "}$!", $readData, $match);
      $data = $match[0];
      break;
    }
  }
  fclose($fp);
  echo $data;
  ?>

整个代码执行完成耗时 0.0009(s)。 

方法三

<?php
  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));
  ?>

整个代码执行完成耗时 0.0003(s)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
发款php蜘蛛统计插件只要有mysql就可用
Oct 12 PHP
PHP目录函数实现创建、读取目录教程实例
Jan 13 PHP
浅谈PHP强制类型转换,慎用!
Jun 06 PHP
解析php dirname()与__FILE__常量的应用
Jun 24 PHP
php的一个简单加密解密代码
Jan 14 PHP
PHP获取当前所在目录位置的方法
Nov 26 PHP
php实现修改新闻时删除图片的方法
May 12 PHP
php图形jpgraph操作实例分析
Feb 22 PHP
php7安装mongoDB扩展的方法分析
Aug 02 PHP
PHP 实现手机端APP支付宝支付功能
Jun 07 PHP
php微信开发之关注事件
Jun 14 PHP
PHP类与对象后期静态绑定操作实例详解
Dec 20 PHP
支付宝支付开发――当面付条码支付和扫码支付实例
Nov 04 #PHP
Redis使用Eval多个键值自增的操作实例
Nov 04 #PHP
php array_slice 取出数组中的一段序列实例
Nov 04 #PHP
PHP获取访问页面HTTP状态码的实现代码
Nov 03 #PHP
PHP之将POST数据转化为字符串的实现代码
Nov 03 #PHP
PHP读取文件的常见几种方法
Nov 03 #PHP
PHP自定义多进制的方法
Nov 03 #PHP
You might like
常用的php ADODB使用方法集锦
2008/03/25 PHP
PHP substr 截取字符串出现乱码问题解决方法[utf8与gb2312]
2011/12/16 PHP
深入解析PHP中逗号与点号的区别
2013/08/05 PHP
浅谈php7的重大新特性
2015/10/23 PHP
php实现异步将远程链接上内容(图片或内容)写到本地的方法
2016/11/30 PHP
PHP中error_reporting函数用法详细介绍
2017/06/11 PHP
tp5(thinkPHP5)框架连接数据库的方法示例
2018/12/24 PHP
在线游戏大家来找茬II
2006/09/30 Javascript
javascript的trim,ltrim,rtrim自定义函数
2008/09/21 Javascript
JavaScript CSS修改学习第三章 修改样式表
2010/02/19 Javascript
解决jquery的.animate()函数在IE6下的问题
2010/12/03 Javascript
js substr、substring和slice使用说明小记
2011/09/15 Javascript
jQuery .attr()和.removeAttr()方法操作元素属性示例
2013/07/16 Javascript
基本DOM节点操作
2017/01/17 Javascript
JavaScript箭头(arrow)函数详解
2017/06/04 Javascript
jquery拖动改变div大小
2017/07/04 jQuery
ES6学习教程之模板字符串详解
2017/10/09 Javascript
Javascript 编码约定(编码规范)
2018/03/11 Javascript
详解如何在vue项目中使用lodop打印插件
2018/09/27 Javascript
浅谈vue项目打包优化策略
2018/09/29 Javascript
vue 使用鼠标滚动加载数据的例子
2019/10/31 Javascript
vue 封装面包屑组件教程
2020/11/16 Javascript
[54:33]2018DOTA2亚洲邀请赛小组赛 A组加赛 Liquid vs Optic
2018/04/03 DOTA
[01:18]PWL开团时刻DAY4——圣剑与抢盾
2020/11/03 DOTA
python进阶教程之模块(module)介绍
2014/08/30 Python
Python 旋转打印各种矩形的方法
2019/07/09 Python
Python 实现的 Google 批量翻译功能
2019/08/26 Python
美国CVS药店官网:CVS Pharmacy
2018/07/26 全球购物
Bose美国官网:购买Bose耳机和音箱
2019/03/10 全球购物
香港连卡佛百货官网:Lane Crawford
2019/09/04 全球购物
单位个人查摆问题及整改措施
2014/10/28 职场文书
2014-2015学年工作总结
2014/11/27 职场文书
2019下半年英语教师的教学工作计划(3篇)
2019/09/25 职场文书
Redis实现一个账号只能登录一个设备
2022/04/19 Redis
windows10 家庭版下FTP服务器搭建教程
2022/08/05 Servers
CentOS7设置ssh服务以及端口修改方式
2022/12/24 Servers