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

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)

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

(0)

相关推荐

  • php实现的http请求封装示例

    本文实例讲述了php的http请求封装.分享给大家供大家参考,具体如下: /** * 发送HTTP请求方法,目前只支持CURL发送请求 * @param string $url 请求URL * @param array $params 请求参数 * @param string $method 请求方法GET/POST * @return array $data 响应数据 */ protected function http($url, $params, $method = 'GET', $hea

  • 深入了解PHP中的Array数组和foreach

    1. 了解数组 PHP 中的数组实际上是一个有序映射.映射是一种把 values 关联到 keys 的类型.详细的解释可参见:PHP.net中的Array数组    . 2.例子:一般的数组 这里,我通过一个简单的例子,并使用图形方式来了解数组. $a = array(3 => 'a', 1 => 'b', 2 => 'c'); echo var_dump($a); [注]:使用箭头描述数组$a各个单元对应某一内存地址的数据值(实际上,它内部结构采用HashTable结构,可以参考鸟哥写

  • PHP获取访问页面HTTP状态码的实现代码

    废话不说了直接上代码 核心代码: /** * 获取远程URL的HTTP状态 * * @version 0.0.1 * @Author Chenjl * * @param string $url 远程URL * @param string $data ture[返回HTTP状态数组] | false[返回状态数值] * * @return mixed */ function getHeaders($url,$data=FALSE){ $_headers = get_headers($url,1);

  • PHP利用超级全局变量$_POST来接收表单数据的实例

    利用$_POST超级全局变量接收表单的数据,然后利用echo输出到页面. 下面是代码: <!doctype html> <html> <head> <title>利用超级全局变量$_POST接收表单</title> <meta http-equiv="content-type" contnet="text/html" charset="utf-8"/> </head&g

  • php使用FFmpeg接口获取视频的播放时长、码率、缩略图以及创建时间

    FFmpeg是一个视频插件,我们可以利用调用FFmpeg接口来获取视频的相关信息,包括视频的播放时长,视频的码率,视频的缩略图以及视频创建时间,本文章向大家介绍php如何使用FFmpeg接口获取视频信息,需要的朋友可以参考一下. FFmpeg获得视频文件的缩略图: function getVideoCover($file,$time,$name) { if(empty($time))$time = '1';//默认截取第一秒第一帧 $strlen = strlen($file); // $vid

  • PHP运行模式汇总

    PHP运行模式有4钟: 1)cgi 通用网关接口(Common Gateway Interface)) 2) fast-cgi 常驻 (long-live) 型的 CGI 3) cli  命令行运行   (Command Line Interface) 4)web模块模式 (apache等web服务器运行的模块模式) 5)ISAPI(Internet Server Application Program Interface) 备注:在PHP5.3以后,PHP不再有ISAPI模式,安装后也不再有p

  • PHP利用超级全局变量$_GET来接收表单数据的实例

    我们在linux上用 touch php_get.html php_get.php创建两个文件. php_get.html文件的代码如下: <!doctype html> <html> <head> <title>超级全局变量$_GET来接收提交的数据,然后返回信息</title> <meta http-equiv="contnet-type" content="text/htm" charset=&

  • PHP之将POST数据转化为字符串的实现代码

    主要用途就是记录POST过来的参数: 以下函数主要原理还是应用递归方式,将多维数组转化为一维数组进行,最后进行数组转字符串处理既可拿到POST过来的数据字符串化: 核心代码: /** * 应用于LOG记录POST参数使用 * * @version 0.0.1 * @Author Chenjl <ciwdream@gmail.com> * * @return string */ function getPostLog(array $_data = array(),$n = ''){ $_gPOS

  • php 时间time与日期date之间的使用详解及区别

    php时间time与日期date之间的使用区别 1.time()函数 PHP中的time()函数,使用echo输出来看是一个很长的整数,里面包含了日期和时间,是计算后的一个值.如果要得到Y-m-d H:i:s这样的日期格式,那么可以使用date方法: date('Y-m-d H:i:s', time()); echo输出它即可得到:2016-1-5 10:20:11 2.日期格式与字符串 我们自己可以构建一个日期格式的字符串,如:2015-1-1 10:20:11.可以使用strtotime()

  • 前端实现文件的断点续传(前端文件提交+后端PHP文件接收)

    早就听说过断点续传这种东西,前端也可以实现一下.断点续传在前端的实现主要依赖着HTML5的新特性,所以一般来说在老旧浏览器上支持度是不高的. 本文通过断点续传的简单例子(前端文件提交+后端PHP文件接收),理解其大致的实现过程 还是先以图片为例,看看最后的样子 一.一些知识准备 断点续传,既然有断,那就应该有文件分割的过程,一段一段的传. 以前文件无法分割,但随着HTML5新特性的引入,类似普通字符串.数组的分割,我们可以可以使用slice方法来分割文件. 所以断点续传的最基本实现也就是:前端通

  • php 输出json及显示json中的中文汉字详解及实例

    php 输出json及显示json中的中文汉字 在php中,我们经常需要将数组输出json,只需要使用json_encode函数处理一下数组即可,但有的时候数组里面有中文,使用json_encode函数处理后中文字符被编码成了Unicode,如何才能在json中显示中文呢?请看下文. 首先介绍一下php输出json格式: 一种最简单的用法,就是把数组直接输出为json,如下: <?php $arr = array('p1'=>'ni"hao','p2'=>2,'ch'=>

  • PHP中获取文件创建日期、修改日期、访问时间的方法

    php获取文件创建时间.修改时间常用代码 filemtime ( string filename ) 返回文件上次被修改的时间,出错时返回 FALSE.时间以 Unix 时间戳的方式返回,可用于 date(). 例如:$a=filemtime("log.txt"); echo "修改时间:".date("Y-m-d H:i:s",$a); filectime ( string filename ) 返回文件上次 inode 被修改的时间,如果出错

  • PHP数组的定义、初始化和数组元素的显示实现代码

    从ASP初入门到PHP,感觉到PHP的强大之一就是内置函数的丰富,比如先前学习的PHP日期时间函数,读写文件的相关函数等都无不表明了PHP的更专业.更令用户的使用得心应手. 一开始我对PHP函数的丰富功能很兴奋,随着对越来越多近乎变态多的函数接触之后,突然联想到了ASP内置函数的稀少,要完成某项特殊功能,常须自定义函数,随着应用的在增多,自己居然也有了一套常用的函数库.然而现在在PHP中,这些功能早已被标准化.规范化而浓缩为内置函数直接使用,曾经的ASP开发人员成为了PHP的普通用户. 但转念一

随机推荐