`

php 读取,分割大文件详解

    博客分类:
  • php
php 
阅读更多

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

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

实现方法:

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

下面是一段用file来取出这具文件最后一行的代码.
整个代码执行完成耗时 116.9613 (s).


$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 &gt; $chunk) ? $chunk : $max - $len;
     fseek($fp, ($len + $seekSize) * -1, SEEK_END);
     $readData = fread($fp, $seekSize) . $readData;

     if (substr_count($readData, "\n") &gt;= $num + 1) {
         preg_match("!(.*?\n){".($num)."}$!", $readData, $match);
         $data = $match[0];
         break;
     }
}
fclose($fp);
echo $data;


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

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

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


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


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

这种方式是最为普遍的方式,它不需要将文件的内容全部读入内存,而是直接通过指针来操作,所以效率是相当高效的.在使用fseek来对文件进行操作时,也有多种不同的方法,效率可能也是略有差别的,下面是常用的两种方法.
方法一:
首先通过fseek找到文件的最后一位EOF,然后找最后一行的起始位置,取这一行的数据,再找次一行的起始位置,再取这一行的位置,依次类推,直到找到了$num行。
实现代码如下
整个代码执行完成耗时 0.0095 (s)


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));


方法二:

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

$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.0003(s)


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

分享到:
评论

相关推荐

    PHP文件读写操作之文件读取方法详解

    除了fgetss()之外,我们还可以使用fgets()读取文件的一行,fgetcsv()读取CSV文件的一行(在读取时,可以通过指定分隔符来进行字段分割),readfile()直接输出文件内容到浏览器,fpassthru()同样输出文件内容到浏览器...

    基于PHP读取csv文件内容的详解

    在使用PHP处理CSV文件时,通常会涉及以下几个方面:打开文件、逐行读取、读取特定行、读取指定行区间以及结合其他函数进行操作。下面将详细解释这些知识点。 首先,读取整个CSV文件的内容,通常会用到`fopen`函数来...

    php断点续传之文件分割合并详解

    断点续传的关键在于将大文件分割成若干小块,然后逐个上传,最后再将这些小块合并成原始文件。下面我们将详细探讨这个过程。 首先,我们需要一个分割文件的脚本,即`split.php`。在这个示例中,`socket.zip`是需要...

    PHP操作MongoDB GridFS 存储文件的详解

    MongoDB GridFS是一个用于在MongoDB数据库中存储大型二进制文件的机制,它将大文件分割成多个小文件块,然后分别存储这些文件块及其元数据。在PHP中操作MongoDB GridFS存储文件需要了解如何连接MongoDB数据库、操作...

    解决PHP超大文件下载,断点续传下载的方法详解

    在处理PHP超大文件下载时,通常会遇到内存溢出的问题,这是因为下载大文件时,PHP需要一次性读取整个文件到内存中,导致内存消耗过大而溢出。为了防止这种情况,一个有效的解决方案是实施断点续传下载机制。断点续传...

    PHP MongoDB GridFS 存储文件的方法详解

    在PHP中,MongoDB GridFS是一种用于存储和检索大型文件的系统,它将大文件分割成小块,以便更有效地存储在数据库中。MongoDB本身不支持大文件的直接存储,因此引入了GridFS作为解决方案。以下是对PHP MongoDB GridFS...

    php成绩查询系统

    PHP提供了一系列函数来读取和操作文件,如`file_get_contents()`用于获取整个文件内容,`file()`用于将文件内容分割成数组,每行一个元素。解析成绩数据时,可能需要使用`explode()`函数来根据分隔符拆分字符串,...

    详解PHP多个进程配合redis的有序集合实现大文件去重

    在处理大数据时,大文件去重是一个常见的需求,特别是在数据清洗和分析的场景中。本文将详细介绍如何利用PHP和Redis的有序集合(Sorted Set)来实现这一目标,尤其是在多进程环境下,提高处理效率。 首先,我们需要...

    ysp_m3u8采集网_m3u8采集_m3u8视频采集_m3u8采集s站_php采集_

    它将大视频文件分割成多个小段TS文件,通过HTTP协议分发,从而实现流式传输。这种方式可以适应不同的网络条件,提高用户体验。 在M3U8视频采集过程中,一次解析源码是指直接解析原始的M3U8文件,获取到视频的TS片段...

    PHP文本式留言板

    当需要显示留言时,PHP读取文本文件的内容并输出到网页上。 ### 二、实现步骤 1. **创建HTML表单** 创建一个HTML文件,例如`messageBoard.html`,用于用户提交留言。表单包括一个文本输入框(用于留言内容)和一...

    PHP在线文字转语音合成源码

    这涉及到文件系统的操作,如创建、写入和读取文件。同时,为了让用户能够在线播放,源码还需要处理音频流,如设置响应头中的Content-Type字段。 **6. 安全与性能优化** 在实际部署时,要考虑安全性问题,比如防止...

    php环境配置(windows)

    - 修改相应的目录权限设置,确保Apache能够正常读取和写入文件。 ### 二、配置PHP #### 1. 设置PHP路径 - 将PHP安装到指定位置,如`C:\php`。 - 添加PHP目录到系统的环境变量Path中,以便命令行工具可以全局访问...

    php_核心编程所有例程.rar

    6. **文件系统操作**:PHP提供了丰富的文件I/O函数,如打开、关闭、读取、写入文件,以及目录操作。这些功能在处理服务器端的文件操作时十分有用。 7. **错误与异常处理**:理解和运用错误报告机制以及异常处理,能...

    php留言板实例子txt数据库源码

    使用`file_get_contents()`读取文件,然后按行分割,每行就是一个留言: ```php &lt;?php $file = 'notes.txt'; $notes = file_get_contents($file); $lines = explode("\n", $notes); foreach ($lines as $line) { ...

    PHP实例开发源码-五笔速查工具 php版.zip

    《PHP五笔速查工具开发详解》 在IT领域,PHP是一种广泛使用的服务器端脚本语言,尤其在网页开发中占据重要地位。本实例“PHP五笔速查工具”是基于PHP实现的一个实用工具,旨在帮助用户快速查询五笔编码,提高汉字...

    php内容分页分隔符

    此方法用于从指定的模板文件中读取内容。模板文件通常是预定义的HTML结构,其中包含占位符,例如 `{Content}` 和 `{NewsPage}`。在 `Content2Html()` 方法中,这些占位符会被实际的内容和页码替换,从而生成最终的...

    用php制作简单分页(从数据库读取记录)的方法详解

    首先,分页的核心思想是将数据集分割成多个较小的块,每块显示在单独的页面上。为了实现这个目的,我们需要计算数据总数和总页数,并根据当前页码来获取当前页需要显示的数据。 分页功能的关键步骤包括以下几个方面...

    MongoDB系列教程(八):GridFS存储详解

    然而,当需要存储大文件,如图片或视频时,由于单个文档大小的限制,直接存储大文件在单个文档中并不理想。这就是 GridFS 登场的地方。 **GridFS 存储详解** GridFS 是 MongoDB 提供的一种存储和检索大文件的标准...

    PHP详细文档

    例如,`strlen()`用于获取字符串长度,`explode()`用于分割字符串,`file_get_contents()`用于读取文件内容,`date()`用于格式化日期和时间。 **PHP数组** 数组在PHP中非常重要,有索引数组和关联数组两种。索引...

    PHP官方手册,可制作电子书

    7. **文件和目录操作**:PHP可以用来读取、写入、创建、删除文件和目录,如fopen、fwrite、fclose、mkdir、rmdir等函数。 8. **错误和异常处理**:PHP通过error_reporting和set_error_handler设置错误处理方式,也...

Global site tag (gtag.js) - Google Analytics