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 批量删除 sql语句
Jun 05 PHP
PHP执行linux系统命令的常用函数使用说明
Apr 27 PHP
让Json更懂中文(JSON_UNESCAPED_UNICODE)
Oct 27 PHP
php中使用preg_replace函数匹配图片并加上链接的方法
Feb 06 PHP
php去除字符串换行符示例分享
Feb 13 PHP
php socket实现的聊天室代码分享
Aug 16 PHP
php查询mssql出现乱码的解决方法
Dec 29 PHP
PHP中使用SimpleXML检查XML文件结构实例
Jan 07 PHP
PHP长连接实现与使用方法详解
Feb 11 PHP
ThinkPHP框架使用redirect实现页面重定向的方法实例分析
Apr 12 PHP
Laravel框架查询构造器 CURD操作示例
Sep 04 PHP
详解Go与PHP的语法对比
May 29 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
DEDE采集大师官方留后门的删除办法
2011/01/08 PHP
php数组中删除元素之重新索引的方法
2014/09/16 PHP
基于ThinkPHP5框架使用QueryList爬取并存入mysql数据库操作示例
2019/05/25 PHP
jQuery阻止冒泡和HTML默认操作
2010/11/17 Javascript
jQuery中的.bind()、.live()和.delegate()之间区别分析
2011/06/08 Javascript
Javascript 键盘事件的组合使用实现代码
2012/05/04 Javascript
javascript获取本机操作系统类型的方法
2015/08/13 Javascript
纯CSS3代码实现滑动开关效果
2015/08/19 Javascript
angular ngClick阻止冒泡使用默认行为的方法
2016/11/03 Javascript
jQuery控制控件文本的长度的操作方法
2016/12/05 Javascript
Web开发中客户端的跳转与服务器端的跳转的区别
2017/03/05 Javascript
Angualrjs 表单验证的两种方式(失去焦点验证和点击提交验证)
2017/05/09 Javascript
javascript 数据存储的常用函数总结
2017/06/01 Javascript
ReactJs设置css样式的方法
2017/06/08 Javascript
axios+Vue实现上传文件显示进度功能
2019/04/14 Javascript
JavaScript监听键盘事件代码实现
2020/06/03 Javascript
JavaScript前端开发时数值运算的小技巧
2020/07/28 Javascript
python实现通过代理服务器访问远程url的方法
2015/04/29 Python
python使用PyGame模块播放声音的方法
2015/05/20 Python
Python 基础教程之包和类的用法
2017/02/23 Python
Python基于tkinter模块实现的改名小工具示例
2017/07/27 Python
关于Django显示时间你应该知道的一些问题
2017/12/25 Python
python re模块的高级用法详解
2018/06/06 Python
python爬虫之自动登录与验证码识别
2020/06/15 Python
python将字符串以utf-8格式保存在txt文件中的方法
2018/10/30 Python
CentOS下Python3的安装及创建虚拟环境的方法
2018/11/28 Python
对django views中 request, response的常用操作详解
2019/07/17 Python
Django 后台获取文件列表 InMemoryUploadedFile的例子
2019/08/07 Python
Python实现数值积分方式
2019/11/20 Python
使用Python实现分别输出每个数组
2019/12/06 Python
Python enumerate() 函数如何实现索引功能
2020/06/29 Python
璀璨的珍珠、密钉和个性化珠宝:Lily & Roo
2021/01/21 全球购物
如何在C# winform中异步调用web services
2015/09/21 面试题
社会学专业求职信
2014/02/24 职场文书
三分钟演讲稿事例
2014/03/03 职场文书
2016年小学植树节活动总结
2016/03/16 职场文书