从最后几行PHP开始读取文件

时间:2018-02-08 14:00:19

标签: php

当主题正在阅读文本文件时,我没有运气。我有一个小脚本来读取日志文件(实时更新)但我想将一些数据发送到DB。

问题是,如果我没有从文件末尾读取统计信息,我将在数据库中获得重复的条目。这不可能发生!

// Keep alive
for (;;)
    {
    $handle = fopen("data.log", "r");
    if (!$handle) die("Open error - data.log");
    while (!feof($handle))
        {
        $line = fgets($handle, 4096);
        // If match with, I output the result
        if (strpos($line, ':gshop_trade:') > 0)
            {
            if (!preg_match('/([\d-: ]+)\s*.*\sformatlog:gshop_trade:userid=(\d+):(.*)item_id=(\d+):expire=(\d+):item_count=(\d+):cash_need=(\d+):cash_left=(\d+).*$/', $line, $data))
                {
                echo "Parsing error on line: {$line}";
                }
            // show the data
            }
        }
    sleep(5);
    }

这个脚本正在运行,但正如我上面提到的,我需要将数据发送给BD。但是,我还需要让脚本运行,使用当前代码,脚本匹配所需的字符串,而不是等待data.log上的新条目,他再次开始读取整个文件。

我看到这个question here并且我测试了但是没有用。当我启动生成" data.log"的服务时,我将启动脚本。但为了防止数据库中的重复条目,我需要阅读最后几行。

我该怎么做?

2 个答案:

答案 0 :(得分:1)

也许你可以使用file_get_contents,爆炸并向后读取数组?

$arr = explode(PHP_EOL, file_get_contents("data.log")); // or file("data.log");
$arr = array_reverse($arr);

foreach($arr as $line){
    // do stuff here in reverse order
}

从上面的评论中我建议这种方法只使用代码中的新数据 它将读取您的日志和文本文件,其中包含上次读取的内容 删除上次读取的内容并使用代码中的新数据。

$logfile = file_get_contents("data.log");
$ReadData = file_get_contents("readdata.txt");

$newdata = str_replace($ReadData, "", $logfile); // this is what is new since last run.
file_put_contents("readdata.txt", $logfile); // save what has been read.

$arr = explode(PHP_EOL, $newdata);

foreach($arr as $line){
    // do your stuff here with the new data.
}

?>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="refresh" content="5"> <!-- This will run the page every five seconds.
    </head>
</html>

答案 1 :(得分:1)

使用ftell()跟踪上一次读数的文件偏移并将结果保存在变量中,并在使用{{3重新打开它以进行下一次读取时跳转到文件中的偏移量}}

$lastPos = 0;
for (;;)
    {
    $handle = fopen("data.log", "r");
    if (!$handle) die("Open error - data.log");
    fseek($handle, $lastPos);    // <--- jump to last read position
    while (!feof($handle))
        {
        $line = fgets($handle, 4096);
        $lastPos = ftell($handle);    // <--- maintain last read position
        // If match with, I output the result
        if (strpos($line, ':gshop_trade:') > 0)
            {
            if (!preg_match('/([\d-: ]+)\s*.*\sformatlog:gshop_trade:userid=(\d+):(.*)item_id=(\d+):expire=(\d+):item_count=(\d+):cash_need=(\d+):cash_left=(\d+).*$/', $line, $data))
                {
                echo "Parsing error on line: {$line}";
                }
            // show the data
            }
        }
    sleep(5);
    }