• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

PHP如何快速读取大文件_php

php 搞代码 7年前 (2018-06-21) 132次浏览 已收录 0个评论

php中,对于文件的读取时,最快捷的方式莫过于使用一些诸如filefile_get_contents之类的函数,简简单单的几行代码就能很漂亮的完成我们所需要的功能。但当所操作的文件是一个比较大的文件时,这些函数可能就显的力不从心, 下面将从一个需求入手来说明对于读取大文件时,常用的操作方法。

需求

有一个800M的日志文件,大约有500多万行, 用PHP返回最后几行的内容。

实现方法

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.直接调用linux的 tail 命令来显示最 后几行

在Linux命令行下,可以直接使用 tail -n 10 access.log 很轻易的显示日志文件最后几行,可以直接用PHP来调用tail命令,执行PHP代码如下:

 <?php $file = 'access.log'; $file = escapeshellarg($file); // 对命令行参数进行安全转义 $line = `tail -n 1 $file`; echo $line; ?>

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

3. 直接使用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--;  }  $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)  {   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 利用 Curl Functions 实现多线程抓取网页和下载文件
  • php读取xml文件总结
  • php error_log() 将错误信息写入一个文件
  • PHP中如何将数组变量写入到文件
  • PHP删除目录及目录下所有文件
  • 如何解决php中并发读写文件冲突的问题
  • php获取目录所有文件并将结果保存到数组的程序

欢迎大家阅读《PHP如何快速读取大文件_php》,跪求各位点评,若觉得好的话请收藏本文,by 搞代码


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:PHP如何快速读取大文件_php

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址