PHP读取大文件的几种方法介绍


Posted in PHP onOctober 27, 2016

读取大文件一直是一个头痛的问题,我们像使用php开发读取小文件可以直接使用各种函数实现,但一到大文章就会发现常用的方法是无法正常使用或时间太长太卡了,下面我们就一起来看看关于php读取大文件问题解决办法,希望例子能帮助到各位。

场景:PHP读取超大文件,例如1G的日志文件,我这里使用的是400M的access.log文件

1、使用file直接读取

<?php
$starttime=microtime_float();
 
ini_set('memory_limit', '-1');
$file = 'testfile.txt';
 
$data = file($file);
$line = $data[count($data) - 1000];
$endtime=microtime_float();
 
echo count($data),"<br/>";
echo $endtime-$starttime;
 
function microtime_float(){
 list($usec, $sec) = explode(" ", microtime());
 return ((float)$usec + (float)$sec);
}
?>

运行结果:10127784 行   共使用了,7.8764359951s

我的电脑是3G内存,此方法不是推荐使用,因为需要把文件全部载入内存

2、使用linux命令  tail

<?php
 
$starttime=microtime_float();
 
$file = 'testfile.txt';
$file = escapeshellarg($file); // 对命令行参数进行安全转义
$line = `tail -n 100 $file`;
 
echo $line,"<br/>";
 
$endtime=microtime_float();
echo $endtime-$starttime;
 
function microtime_float(){
 list($usec, $sec) = explode(" ", microtime());
 return ((float)$usec + (float)$sec);
}
 
//end

运行结果:只使用了几毫秒、轻松搞定、这种方法不能在windows下使用

3、使用fseek函数

这种方式是最为普遍的方式,它不需要将文件的内容全部读入内容,因为PHP是C写的,所以实现的时候也类似C读取文件,通过指针的移动,所以效率是相当高效的。在使用fseek来对文件进行操作时,也有多种不同的方法,效率可能也是略有差别的,

下面是常用的几种方法

方法一:使用fopen打开文件(从文件指针资源句柄)

<?php
$starttime=microtime_float();
 
$file = 'testfile.txt';
$fp = fopen($file, "r+");
 
$line = 100;
$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,"<br/>";
$endtime=microtime_float();
 
echo $endtime-$starttime;
 
function microtime_float(){
 list($usec, $sec) = explode(" ", microtime());
 return ((float)$usec + (float)$sec);
}
?>

运行结果:0.338493108749

方法二:一块一块的读取

<?php
$starttime=microtime_float();
 
$file = 'testfile.txt';
$fp = fopen($file, "r");
$num = 10;
$chunk = 4096;//4K的块
$fs = sprintf("%u", filesize($file));
$readData='';
$max = (intval($fs) == PHP_INT_MAX) ? PHP_INT_MAX : $fs;
 
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) {
 
 $ns=substr_count($readData, "\n")-$num+2;
 preg_match('/(.*?\n){'.$ns.'}/',$readData,$match);
 $data = $match[1];
 break;
}
}
fclose($fp);
echo $data,"<br/>";
 
 
$endtime=microtime_float();
 
echo $endtime-$starttime;
 
function microtime_float(){
 list($usec, $sec) = explode(" ", microtime());
 return ((float)$usec + (float)$sec);
}
?>

运行时间:0.00199198722839

使用fgets函数,一行一行读取

<?php
$file = fopen("testfile.txt","r");
 while(!feof($file))
 {
   echo fgets($file);
 }
 fclose($file);

spl库函数

<?php
try{
  foreach( new SplFileObject('testfile.txt') as $line)
  echo $line.'<br />';
}catch (Exception $e){
  echo $e->getMessage();
}

另外网上有很多按照块读取文件的,有兴趣的读者可以试试,我试了没成功,好像必须含有换行符“\n”才可以。

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

PHP 相关文章推荐
php桌面中心(二) 数据库写入
Mar 11 PHP
国外比较好的几个的Php开源建站平台小结
Apr 22 PHP
深入解析PHP内存管理之谁动了我的内存
Jun 20 PHP
codeigniter框架批量插入数据
Jan 09 PHP
php数组查找函数总结
Nov 18 PHP
Opcache导致php-fpm崩溃nginx返回502
Mar 02 PHP
PHP中each与list用法分析
Jan 08 PHP
常用PHP封装分页工具类
Jan 14 PHP
详解yii2实现分库分表的方案与思路
Feb 03 PHP
thinkphp中的多表关联查询的实例详解
Oct 12 PHP
实例讲解PHP中使用命名空间
Jan 27 PHP
laravel 使用事件系统统计浏览量的实现
Oct 16 PHP
php array_multisort 对数组进行排序详解及实例代码
Oct 27 #PHP
PHP中的密码加密的解决方案总结
Oct 26 #PHP
php 解析xml 的四种方法详细介绍
Oct 26 #PHP
PHP 以POST方式提交XML、获取XML,解析XML详解及实例
Oct 26 #PHP
php 生成签名及验证签名详解
Oct 26 #PHP
PHP XML和数组互相转换详解
Oct 26 #PHP
PHP对XML内容进行修改和删除实例代码
Oct 26 #PHP
You might like
Yii2使用$this-&gt;context获取当前的Module、Controller(控制器)、Action等
2017/03/29 PHP
laravel 解决paginate查询多个字段报错的问题
2019/10/22 PHP
在 PHP 和 Laravel 中使用 Traits的方法
2019/11/13 PHP
PHP程序员简单的开展服务治理架构操作详解(二)
2020/05/14 PHP
javascript parseInt 函数分析(转)
2009/03/21 Javascript
Extjs ajax同步请求时post方式参数发送方式
2009/08/05 Javascript
基于jQuery的简单的列表导航菜单
2011/03/02 Javascript
js弹出层之1:JQuery.Boxy (二)
2011/10/06 Javascript
jQuery侧边栏随窗口滚动实现方法
2013/03/04 Javascript
JavaScript作用域链使用介绍
2013/08/29 Javascript
js与jQuery 获取父窗、子窗的iframe
2013/12/20 Javascript
基于jquery的simpleValidate简易验证插件
2014/01/31 Javascript
JS对象与json字符串格式转换实例
2014/10/28 Javascript
javascript和jquery实现设置和移除文本框默认值效果代码
2015/01/13 Javascript
微信小程序 登录实例详解
2017/01/16 Javascript
JS实现css hover操作的方法示例
2017/04/07 Javascript
bootstrap 路径导航 分页 进度条的实例代码
2018/08/06 Javascript
angular异步验证防抖踩坑实录
2019/12/01 Javascript
微信小程序实现录制、试听、上传音频功能(带波形图)
2020/02/27 Javascript
vue+iview框架实现左侧动态菜单功能的示例代码
2020/07/23 Javascript
进一步理解Python中的函数编程
2015/04/13 Python
python实现ID3决策树算法
2018/08/29 Python
html5的新增的标签和废除的标签简要概述
2013/02/20 HTML / CSS
Html5饼图绘制实现统计图的方法
2020/08/05 HTML / CSS
财务出纳岗位职责
2014/02/03 职场文书
见习期自我鉴定范文
2014/03/19 职场文书
1亿有多大教学反思
2014/05/01 职场文书
保研推荐信
2014/05/09 职场文书
购房公证委托书(2014版)
2014/09/12 职场文书
求职自我评价范文100字
2014/09/23 职场文书
篮球比赛通讯稿
2015/07/18 职场文书
2016年国庆节新闻稿范文
2015/11/25 职场文书
党员干部学习十八届五中全会精神心得体会
2016/01/05 职场文书
零基础学java之循环语句的使用
2022/04/10 Java/Android
MySQL中的全表扫描和索引树扫描
2022/05/15 MySQL
前端传参数进行Mybatis调用mysql存储过程执行返回值详解
2022/08/14 MySQL