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读写文件的方法(生成HTML)
Nov 27 PHP
Php Cookie的一个使用注意点
Nov 08 PHP
php简单开启gzip压缩方法(zlib.output_compression)
Apr 13 PHP
php时间戳转换的示例
Mar 31 PHP
PHP扩展CURL的用法详解
Jun 20 PHP
php遍历数组的4种方法总结
Jul 05 PHP
PHP缓存机制Output Control详解
Jul 14 PHP
php保存二进制原始数据为图片的程序代码
Oct 14 PHP
php mailer类调用远程SMTP服务器发送邮件实现方法
Mar 04 PHP
简要剖析PHP的Yii框架的组件化机制的基本知识
Mar 17 PHP
PHP和MYSQL实现分页导航思路详解
Apr 11 PHP
php设计模式之正面模式实例分析【星际争霸游戏案例】
Mar 24 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中PDO基础教程 入门级
2011/09/04 PHP
PHP获取http请求的头信息实现步骤
2012/12/16 PHP
探讨PHP JSON中文乱码的解决方法详解
2013/06/06 PHP
php中http与https跨域共享session的解决方法
2014/12/20 PHP
php使用MySQL保存session会话的方法
2015/06/26 PHP
PHP图片添加水印功能示例小结
2016/10/03 PHP
php实现给二维数组中所有一维数组添加值的方法
2017/02/04 PHP
PHP pthreads v3下worker和pool的使用方法示例
2020/02/21 PHP
javascript编程起步(第五课)
2007/02/27 Javascript
Javascript中eval函数的使用方法与示例
2007/04/09 Javascript
Ext面向对象开发实践(续)
2008/11/18 Javascript
javascript学习笔记(三) String 字符串类型介绍
2012/06/19 Javascript
jquery 中ajax执行的优先级
2015/06/22 Javascript
浅谈jQuery 中的事件冒泡和阻止默认行为
2016/05/28 Javascript
Javascript打印局部页面实例
2016/06/21 Javascript
Wireshark基本介绍和学习TCP三次握手
2016/08/15 Javascript
JavaScript中for循环的几种写法与效率总结
2017/02/03 Javascript
Node.js readline模块与util模块的使用
2018/03/01 Javascript
vue和webpack项目构建过程常用的npm命令详解
2018/06/15 Javascript
jQuery访问json文件中数据的方法示例
2019/01/28 jQuery
python网络编程实例简析
2014/09/26 Python
python复制列表时[:]和[::]之间有什么区别
2018/10/16 Python
pandas 对group进行聚合的例子
2019/12/27 Python
python GUI库图形界面开发之PyQt5简单绘图板实例与代码分析
2020/03/08 Python
弄清Pytorch显存的分配机制
2020/12/10 Python
HTML5之web workers_动力节点Java学院整理
2017/07/17 HTML / CSS
html5简介及新增功能介绍
2020/05/18 HTML / CSS
如何利用cmp命令比较文件
2013/09/23 面试题
EJB3.1都有哪些改进
2012/11/17 面试题
2014两会学习心得:时代的发展
2014/03/17 职场文书
科学发展观标语
2014/10/08 职场文书
师范生教育见习总结
2015/06/23 职场文书
欠条格式范本
2015/07/03 职场文书
粗暴解决CUDA out of memory的问题
2021/05/22 Python
Python如何将list中的string转换为int
2022/07/15 Ruby
Pytorch中expand()的使用(扩展某个维度)
2022/07/15 Python