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 相关文章推荐
第二节--PHP5 的对象模型
Nov 16 PHP
PHP 将逗号、空格、回车分隔的字符串转换为数组的函数
Jun 07 PHP
PHP运行环境配置与开发环境的配置(图文教程)
Jun 04 PHP
解析php中heredoc的使用方法
Jun 17 PHP
根据中文裁减字符串函数的php代码
Dec 03 PHP
php文件操作之小型留言本实例
Jun 20 PHP
php把数组值转换成键的方法
Jul 13 PHP
WordPress分页伪静态加html后缀
Jun 08 PHP
浅谈mysql_query()函数的返回值问题
Sep 05 PHP
ThinkPHP中类的构造函数_construct()与_initialize()的区别详解
Mar 13 PHP
浅谈PHP5.6 与 PHP7.0 区别
Oct 09 PHP
laravel 错误处理,接口错误返回json代码
Oct 25 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实现补齐关闭的HTML标签
2016/03/22 PHP
深入解析PHP底层机制及相关原理
2020/12/11 PHP
Avengerls vs Newbee BO3 第一场2.18
2021/03/10 DOTA
IE8提示Invalid procedure call or argument 异常的解决方法
2012/09/30 Javascript
详解JavaScript中undefined与null的区别
2014/03/29 Javascript
基于jQuery的JavaScript模版引擎JsRender使用指南
2014/12/29 Javascript
js对象基础实例分析
2015/01/13 Javascript
jquery增加和删除元素的方法
2015/01/14 Javascript
javascript强制点击广告的方法
2015/02/06 Javascript
使用jquery组件qrcode生成二维码及应用指南
2015/02/22 Javascript
jQuery选择器源码解读(一):Sizzle方法
2015/03/31 Javascript
jquery实现Li滚动时滚动条自动添加样式的方法
2015/08/10 Javascript
深入理解JavaScript 函数
2016/06/06 Javascript
jQuery实现指定区域外单击关闭指定层的方法【经典】
2016/06/22 Javascript
js实现常用排序算法
2016/08/09 Javascript
JQuery 获取Dom元素的实例讲解
2017/07/08 jQuery
p5.js绘制创意自画像
2019/11/04 Javascript
解决vue+elementui项目打包后样式变化问题
2020/08/03 Javascript
通过高德地图API获得某条道路上的所有坐标用于描绘道路的方法
2020/08/24 Javascript
Python脚本判断 Linux 是否运行在虚拟机上
2015/04/25 Python
在Python中marshal对象序列化的相关知识
2015/07/01 Python
使用Python判断质数(素数)的简单方法讲解
2016/05/05 Python
Python和C/C++交互的几种方法总结
2017/05/11 Python
Python 含参构造函数实例详解
2017/05/25 Python
python enumerate函数的使用方法总结
2017/11/15 Python
Python编程pygal绘图实例之XY线
2017/12/09 Python
python for和else语句趣谈
2019/07/02 Python
python装饰器相当于函数的调用方式
2019/12/27 Python
巴西最大的家具及装饰用品店:Mobly
2017/10/11 全球购物
介绍下Java中==和equals的区别
2013/09/01 面试题
《雨霖铃》教学反思
2014/02/22 职场文书
单位工作证明格式模板
2014/10/04 职场文书
签字仪式主持词
2015/07/03 职场文书
素质教育培训心得体会
2016/01/19 职场文书
导游词之岳阳楼
2019/09/25 职场文书
html实现弹窗的实例
2021/06/09 HTML / CSS