在PHP中,对于文件的读取时,最快捷的方式莫过于使用一些诸如file、file_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)

转载于:https://www.cnblogs.com/52php/p/5675737.html

PHP如何快速读取大文件相关推荐

  1. PHP几个快速读取大文件例子

    PHP几个快速读取大文件例子 感谢 把我给崩了 的投递 时间:2014-10-16 来源:三联 在PHP中,对于文件的读取时,最快捷的方式莫过于使用一些诸如file.file_get_contents ...

  2. php -- 读取大文件

    在PHP中,对于文件的读取时,最快捷的方式莫过于使用一些诸如file.file_get_contents之类的函数,简简单单的几行代码就能 很漂亮的完成我们所需要的功能.但当所操作的文件是一个比较大的 ...

  3. linux dd 截文件,Linux使用dd命令快速生成大文件(转)

    dd命令可以轻易实现创建指定大小的文件,如 dd if=/dev/zero of=test bs=1M count=1000 会生成一个1000M的test文件,文件内容为全0(因从/dev/zero ...

  4. python读文件代码-简单了解Python读取大文件代码实例

    这篇文章主要介绍了简单了解Python读取大文件代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 通常对于大文件读取及处理,不可能直接加载到内 ...

  5. Java高效读取大文件

    1.概述 本教程将演示如何用Java高效地读取大文件.这篇文章是Baeldung(http://www.baeldung.com/) 上"Java--回归基础"系列教程的一部分. ...

  6. linux目录怎么自动生成,情景linux--如何快速生成大文件?

    情景 在写情景linux--如何解决服务器日志过大导致的磁盘空间不足?(实践篇)时,因为要实际演示,所以需要快速创建一个大文件.其实,在实际工作过程中,有些时候是有这种需求的.今天就将其作为一个话题探 ...

  7. Java高效读取大文件(转)

    Java高效读取大文件 1.概述 本教程将演示如何用Java高效地读取大文件.这篇文章是Baeldung(http://www.baeldung.com/) 上"Java--回归基础&quo ...

  8. python读取大文件的某行_python 大文件以行为单位读取方式比对

    先前需要做一个使用python读取大文件(大于1G),并逐条存入内存进行处理的工作.做了很多的尝试,最终看到了如下的文章. 该文章实际上提供了集中读取大文件的方式,先经过测试总结如下 1. for l ...

  9. MATLAB快速读取STL文件

    MATLAB快速读取STL文件 一.STL文件格式 binary格式 ascii格式stl 二.开源代码 安装方法 使用方法 三.快速读取 binary格式stl ascii格式stl 四.效果对比 ...

最新文章

  1. 浅谈测试驱动开发(TDD)
  2. [swustoj 856] Huge Tree
  3. jQuery表格排序总成-tablesorter
  4. C#算法设计查找篇之05-二叉树查找
  5. 只用我的提取程序取了800多条产品信息
  6. 补第一阶段冲刺站立会议5(5月17日)
  7. 解析rtcm32报文工具_RTCM数据格式实时处理方法应用
  8. 2022考研计算机-软件工程教程
  9. 抖音短视频无水印下载方法
  10. 电脑计算机快捷键切换桌面,电脑切换界面的快捷键是什么_电脑切换桌面快捷键怎么用-win7之家...
  11. python 打包exe(包含把资源文件打进包)
  12. 帝国php调用文章列表,帝国cms教程内容页面调用当前会员信息和文章数量以及文章列表...
  13. #猜数游戏 之心中无女人猜数自然神,你能一次猜对吗?
  14. 我的世界服务器怎么修改id,我的世界端游怎么改名字
  15. detectron2 c++ 部署笔记
  16. visual stdio 2015社区版、专业版的下载
  17. 密码破解工具John the Ripper使用说明
  18. foxmail邮件导入Outlook 2010
  19. 社会化三方分享集成详细介绍(友盟)
  20. 河道中心线提取、平均宽度计算(Arcgis+CAD)

热门文章

  1. Android之深入WebView
  2. Android JNI学习(四)——JNI的常用方法的API
  3. python不同版本安装;第三方库的安装
  4. oracle如何查询排行第二,Oracle优化查询改写(第二章-给查询结果排序)
  5. ajxs跨域 php_PHP Ajax 跨域问题最佳解决方案
  6. 安卓 background的图片随着textview的大小而改变_关于CSS中的背景属性background简述...
  7. 【Elasticsearch】我在 Elasticsearch 集群内应该设置多少个分片?
  8. 【clickhouse】Clickhouse 的group_concat 实现
  9. 【Java】Java中ThreadLocal简介以及源码
  10. 95-140-132-源码-transform-算子Join