PHP操作超大日志文件

作者: dino.ma 分类: PHP 发布时间: 2019-05-14 17:35

php工程师的晋级不仅仅是一个curd boy,你还需要懂得更多计算机基础知识。

如图我生成一个15g的日志文件,其中字段为$uid\t支付时间\t支付金额

其实整体的思路就是,在做开发时需要有使用内存的概念,因为每一台服务器的php允许使用的内存都是既定的,那么在这种情况下来讲,我们的php脚本所占用内存是坚决不能超出php.ini设置的memory_limit,那么如果我们想解析读取操作一串大的文件怎么办?

譬如php的内存只有2g,但是我们需要操作一个15g的文件?我们有方法么?

当然有,我们只需要在内存占用允许的情况下,一次性把buffer打满之后进行后续业务操作。或者逐行读取(效率坡低)都可以满足在有限内存的情况下去读取大文件。

那么废话不多说,直接上代码。

<?php
declare(strict_types = 1);

function writeLog(string $path = '')
{
    if (!file_exists($path)) {
        throw new Exception('文件不存在');
    }
    if (!is_writable($path)) {
        throw new Exception('文件不可写');
    }
    $obj = new SplFileObject($path, 'w');
    //500000000
    $msg = '';
    for ($i = 1; $i <500000000; $i++) {
        $uid = $i%100000;
        $msg .= $uid.'\t2019-10-18 10:00:11\t2000'.PHP_EOL;
        if (($i % 50000) == 0) {
            $obj->fwrite($msg);
            $msg = '';
        }
    }
}


function readLog(string $path = '')
{
    ini_set('memory_limit', '2G');
    if (!file_exists($path)) {
        throw new Exception('文件不存在'.$path);
    }
    if (!is_readable($path)) {
        throw new Exception('文件不可读'.$path);
    }

    $begin = microtime(true);
    $fp = fopen($path, 'r');
    while (!feof($fp)) {
        fread($fp, 38000000);
    }
    fclose($fp);

    $end = microtime(true);
    echo "cost : ".( $end - $begin ).' sec'.PHP_EOL;
    exit('ok');
}
$path = __DIR__.'/payment.log';
//初始化日志文件
//writeLog($path);
readLog($path);

发表评论

电子邮件地址不会被公开。 必填项已用*标注