php读取php内容-PHP读取并操作大文件,超出内存大小,三种方式

2023-08-29 0 1,811 百度已收录

2019独角兽企业急聘Python工程师标准>>>

php中,读取文件时,最快的方式就是使用file、file_get_contents等一些函数。 简单的几行代码就可以漂亮的完成我们需要的功能。 但是,当所操作的文件是比较大的文件时,这些功能可能就不够用了。 下面将从一个需求开始说明读取大文件的常用操作方法。

需要

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

实现方法

1.简单粗暴php读取php内容,只需使用文件功能直接操作

注意:由于file函数一次性将所有内容读入显存,而php避免一些写得不好的程序占用过多显存而造成系统显存不足,导致服务器宕机,所以默认限制为仅显存最大使用量为16M,通过php.ini中的memory_limit = 16M来设置,如果该值设置为-1,则显存使用量不受限制。

下面是一段使用file提取文件最后一行的代码。

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

完成整个代码的执行花费了116.9613(s)。 很容易导致内存耗尽而导致设备死机或无响应

php读取php内容-PHP读取并操作大文件,超出内存大小,三种方式

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

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

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

整个代码执行时间为0.0034(s)

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

php读取php内容-PHP读取并操作大文件,超出内存大小,三种方式

这种方法是最常用的方法。 它不需要将文件的所有内容读入content中,而是直接通过指针进行操作,因此效率相当高效。 使用fseek对文件进行操作时,也有很多区别。 的方式,效率也可能略有不同,以下是常用的两种方式。

方法一

首先通过fseek找到文件的最后一个EOF,然后找到最后一行的起始位置,得到这一行的数据,然后找到下一行的起始位置,然后取这一行的位置,以此类推php读取php内容,直到找到 $num 为止。

实现代码如下

$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

php读取php内容-PHP读取并操作大文件,超出内存大小,三种方式

整个代码执行耗时0.0095(s)

方法二

仍然采用fseek的形式从文件末尾开始读取,不过此时并不是一个一个的读取,而是一个一个的读取。 读取一条数据时,将读取到的数据放入一个buf中,然后通过换行符(n)的个数来判断最后$num行数据是否已经读取完毕。

实现代码如下

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

php读取php内容-PHP读取并操作大文件,超出内存大小,三种方式

整个代码执行需要 0.0009(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));

整个代码执行完成需要 0.0003(s)

或者借助linux管道

$handle = popen("cat access.log 2>&1", 'r');
while(!feof($handle))
{
    echo $line = fgets($handle);
}
pclose($handle);

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

悟空资源网 php php读取php内容-PHP读取并操作大文件,超出内存大小,三种方式 https://www.wkzy.net/game/172186.html

常见问题

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务