需求: 现有一个1G左右的日志文件,大约有500多万行, 用php返回最后几行的内容。

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

1. 直接采用file函数来操作

由于 file函数是一次性将所有内容读入内存,而php为了防止一些写的比较糟糕的程序占用太多的内存而导致系统内存不足,使服务器出现宕机,所以默认情况下 限制只能最大使用内存16M,这是通过php.ini里的memory_limit = 16M来进行设置,这个值如果设置-1,则内存使用量不受限制。

下面是一段用file来取出这具文件最后一行的代码。代码执行大概2分钟左右。

  1. $fp = fopen($file, "r");
  2. $num = 10;
  3. $chunk = 4096;
  4. $fs = sprintf("%u", filesize($file));
  5. $max = (intval($fs) == PHP_INT_MAX) ? PHP_INT_MAX : filesize($file);
  6. for ($len = 0; $len < $max; $len += $chunk) {
  7. $seekSize = ($max - $len > $chunk) ? $chunk : $max - $len;
  8. fseek($fp, ($len + $seekSize) * -1, SEEK_END);
  9. $readData = fread($fp, $seekSize) . $readData;
  10.  
  11. if (substr_count($readData, "\n") >= $num + 1) {
  12. preg_match("!(.*?\n){".($num)."}$!", $readData, $match);
  13. $data = $match[0];
  14. break;
  15. }
  16. }
  17. fclose($fp);
  18. echo $data;

我机器是2个G的内存,当按下F5运行时,系统直接变灰,差不多20分钟后才恢复过来,可见将这么大的文件全部直接读入内存,后果是多少严重,所以不在万不得以,memory_limit这东西不能调得太高,否则只有打电话给机房,让reset机器了。

2.直接调用linux的tail命令来显示最后几行

在linux命令行下,可以直接使用tail -n 10 access.log很轻易的显示日志文件最后几行,可以直接用php来调用tail命令,执行php代码如下.整个代码执行完成耗时 0.0034 (s)

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

3. 直接使用php的fseek来进行文件操作

这种方式是最为普遍的方式,它不需要将文件的内容全部读入内存,而是直接通过指针来操作,所以效率是相当高效的.在使用fseek来对文件进行操作时,也有多种不同的方法,效率可能也是略有差别的,下面是常用的两种方法.

方法一:

首先通过fseek找到文件的最后一位EOF,然后找最后一行的起始位置,取这一行的数据,再找次一行的起始位置,再取这一行的位置,依次类推,直到找到了$num行。

  1. function tail($fp,$n,$base=5)
  2. {
  3. assert($n>0);
  4. $pos = $n+1;
  5. $lines = array();
  6. while(count($lines)< =$n){
  7. try{
  8. fseek($fp,-$pos,SEEK_END);
  9. } catch (Exception $e){
  10. fseek(0);
  11. break;
  12. }
  13. $pos *= $base;
  14. while(!feof($fp)){
  15. array_unshift($lines,fgets($fp));
  16. }
  17. }
  18. return array_slice($lines,0,$n);
  19. }
  20. var_dump(tail(fopen("access.log","r+"),10));

方法二:

还是采用fseek的方式从文件最后开始读,但这时不是一位一位的读,而是一块一块的读,每读一块数据时,就将读取后的数据放在一个buf里,然后通过换行符(\n)的个数来判断是否已经读完最后$num行数据.

  1. $fp = fopen($file, "r");
  2. $line = 10;
  3. $pos = -2;
  4. $t = " ";
  5. $data = "";
  6. while ($line > 0) {
  7. while ($t != "\n") {
  8. fseek($fp, $pos, SEEK_END);
  9. $t = fgetc($fp);
  10. $pos --;
  11. }
  12. $t = " ";
  13. $data .= fgets($fp);
  14. $line --;
  15. }
  16. fclose ($fp);
  17. echo $data

方法三:

  1. ini_set('memory_limit','-1');
  2. $file = 'access.log';
  3. $data = file($file);
  4. $line = $data[count($data)-1];
  5. echo $line;

PHP对大文件的处理思路的更多相关文章

  1. HTML5 大文件断点续传完整思路整理

    需求: 支持大文件批量上传(20G)和下载,同时需要保证上传期间用户电脑不出现卡死等体验: 内网百兆网络上传速度为12MB/S 服务器内存占用低 支持文件夹上传,文件夹中的文件数量达到1万个以上,且包 ...

  2. C# IO操作(四)大文件拷贝(文件流的使用)、文件编码

         大文件拷贝(文件流的使用).文件编码 首先说一下大文件拷贝和文件流,因为计算机的内存资源是有限的,面对几个G甚至更大的文件,需要通过程序来完成拷贝,就需要用到文件流(因为我们无法做到把文件一 ...

  3. PHP搭建大文件切割分块上传功能

    背景 在网站开发中,文件上传是很常见的一个功能.相信很多人都会遇到这种情况,想传一个文件上去,然后网页提示"该文件过大".因为一般情况下,我们都需要对上传的文件大小做限制,防止出现 ...

  4. asp.net配置web.config支持jQuery.Uploadify插件上传大文件

    配置web.config有两处地方需要配置,分别是集成模式和经典模式. 集成模式: <!--文件上传大小设置--> <httpRuntime requestValidationMod ...

  5. Java多线程读取大文件

    前言 今天是五一假期第一天,按理应该是快乐玩耍的日子,但是作为一个北漂到京师的开发人员,实在难想出去那玩耍.好玩的地方比较远,近处又感觉没意思.于是乎,闲着写篇文章,总结下昨天写的程序吧. 昨天下午朋 ...

  6. 基于RMI服务传输大文件的完整解决方案

    基于RMI服务传输大文件,分为上传和下载两种操作,需要注意的技术点主要有三方面,第一,RMI服务中传输的数据必须是可序列化的.第二,在传输大文件的过程中应该有进度提醒机制,对于大文件传输来说,这点很重 ...

  7. ASP.NET 大文件下载的实现思路及代码

    文件下载是一个网站最基本的功能,ASP.NET网站的文件下载功能实现也很简单,但是如果遇到大文件的下载而不做特殊处理的话,那将会出现不可预料的后果.本文就基于ASP.NET提供大文件下载的实现思路及代 ...

  8. iOS开发网络请求——大文件的多线程断点下载

    iOS开发中网络请求技术已经是移动app必备技术,而网络中文件传输就是其中重点了.网络文件传输对移动客户端而言主要分为文件的上传和下载.作为开发者从技术角度会将文件分为小文件和大文件.小文件因为文件大 ...

  9. WCF大文件传输

    WCF传输文件的时候可以设置每次文件的传输大小,如果是小文件的时候,可以很方便的将文件传递到服务端,但是如果文件比较大的话,就不可取了 遇到大文件的话可以采取分段传输的方式进行文件传输 思路: 1.客 ...

随机推荐

  1. gcc编译器基本命令和vi编辑器2

    !1 os fen时 看电影 聊天.支持多核处理器 分任务 已经绝迹cpu Trobe c 分任务操作系统三大组成部分内核,命令解释器(shell外壳),文件系统2修改文件日期或(创建文件)命令:to ...

  2. (转载)OC学习篇之---概述

    前言 终于开启了OC的学习篇了,之前由于工作上的事,学习就一直搁浅了,不过最近由于各种原因,感觉必须要开启iOS的开发旅程了,不然就老了.因为之前一直是做Android的,所以学习iOS来就没那么费劲 ...

  3. Tkinter教程之Frame篇

    本文转载自:http://blog.csdn.net/jcodeer/article/details/1811339 '''Tkinter教程之Frame篇'''#Frame就是屏幕上的一块矩形区域, ...

  4. 重新执笔,已是大三!Jekyll自定义主题开发

    前言 “一转眼忘了时间 丢了感觉 黑了世界 再逞强 再疯狂 也会伤 不知 不觉 后知 后觉 然后 发现 失去 知觉 ”——<一吻不天荒> 感言 时间是把双刃剑,什么解决不了,忧烦的,慢慢变 ...

  5. 虚拟桌面基础架构(VDI)与终端服务和传统PC对比

    VDI(Virtual Desktop Infrastructure),即虚拟桌面基础架构,正迅速成为一个热门词汇,它将颠覆企业向终端用户交付应用的游戏规则.这篇专题就是想通过VDI与两种传统技术的对 ...

  6. voip的会议服务器Conference Servers

    http://openmcu.ru/eng.htm openmcu:   http://h323plus.cvs.sourceforge.net/viewvc/h323plus/application ...

  7. Apache Spark Streaming的优点

    Apache Spark Streaming的优点: (1)优势及特点 1)多范式数据分析管道:能和 Spark 生态系统其他组件融合,实现交互查询和机器学习等多范式组合处理. 2)扩展性:可以运行在 ...

  8. Contest 7.21(贪心专练)

    这一次都主要是贪心练习 练习地址http://acm.hust.edu.cn/vjudge/contest/view.action?cid=26733#overview Problem APOJ 13 ...

  9. Java常用类(String、StringBuffer、Math、Arrays)

    1.String 操作对象时会重新分配堆内存,栈内存的引用会重新指向新的堆内存 2.StringBuffer(字符串缓存区) 操作的对象一直都是一个 3.Math Math.max(xx,xx); M ...

  10. [转]省市二级联动(纯js实现)

    转至:http://www.jb51.net/article/41556.htm 实现原理: set_city("省名称",市select对象); 判断市select对象是否为空, ...