php 从文件中读取最后一行

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1510141/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 02:52:34  来源:igfitidea点击:

Read last line from file

phpfilefile-io

提问by Bogdan Constantinescu

I've been bumping into a problem. I have a log on a Linux box in which is written the output from several running processes. This file can get really big sometimes and I need to read the last line from that file.

我遇到了一个问题。我在 Linux 机器上有一个日志,其中写入了几个正在运行的进程的输出。这个文件有时会变得非常大,我需要读取该文件的最后一行。

The problem is this action will be called via an AJAX request pretty often and when the file size of that log gets over 5-6MB it's rather not good for the server. So I'm thinking I have to read the last line but not to read the whole file and pass through it or load it in RAM because that would just load to death my box.

问题是此操作将经常通过 AJAX 请求调用,并且当该日志的文件大小超过 5-6MB 时,这对服务器来说并不好。所以我想我必须阅读最后一行,而不是阅读整个文件并通过它或将它加载到 RAM 中,因为这只会加载到我的盒子里。

Is there any optimization for this operation so that it run smooth and not harm the server or kill Apache?

此操作是否有任何优化,使其运行顺畅,不会损害服务器或杀死 Apache?

Other option that I have is to exec('tail -n 1 /path/to/log')but it doesn't sound so good.

我还有其他选择,exec('tail -n 1 /path/to/log')但听起来不太好。

Later edit: I DO NOT want to put the file in RAM because it might get huge. fopen()is not an option.

稍后编辑:我不想将文件放在 RAM 中,因为它可能会变得很大。fopen()不是一个选择。

回答by Ionu? G. Stan

This should work:

这应该有效:

$line = '';

$f = fopen('data.txt', 'r');
$cursor = -1;

fseek($f, $cursor, SEEK_END);
$char = fgetc($f);

/**
 * Trim trailing newline chars of the file
 */
while ($char === "\n" || $char === "\r") {
    fseek($f, $cursor--, SEEK_END);
    $char = fgetc($f);
}

/**
 * Read until the start of file or first newline char
 */
while ($char !== false && $char !== "\n" && $char !== "\r") {
    /**
     * Prepend the new char
     */
    $line = $char . $line;
    fseek($f, $cursor--, SEEK_END);
    $char = fgetc($f);
}

echo $line;

回答by NawaMan

Use fseek. You seek to the last position and seek it backward (use ftellto tell the current position) until you find a "\n".

使用fseek。您寻找到最后一个位置并向后寻找(使用ftell告诉当前位置),直到找到“\n”。


$fp = fopen(".....");
fseek($fp, -1, SEEK_END); 
$pos = ftell($fp);
$LastLine = "";
// Loop backword util "\n" is found.
while((($C = fgetc($fp)) != "\n") && ($pos > 0)) {
    $LastLine = $C.$LastLine;
    fseek($fp, $pos--);
}

NOTE: I've not tested. You may need some adjustment.

注意:我没有测试过。您可能需要进行一些调整。

UPDATE: Thanks Syntax Errorfor pointing out about empty file.

更新:感谢Syntax Error您指出空文件。

:-D

:-D

UPDATE2: Fixxed another Syntax Error, missing semicolon at $LastLine = ""

UPDATE2:修复了另一个语法错误,缺少分号 $LastLine = ""

回答by Abdalla Mohamed Aly Ibrahim

this the code of Ionu? G. Stan

这是Ionu的代码?G·斯坦

i modified your code a little and made it a function for reuseability

我稍微修改了您的代码并使其成为可重用的函数

function read_last_line ($file_path){



$line = '';

$f = fopen($file_path, 'r');
$cursor = -1;

fseek($f, $cursor, SEEK_END);
$char = fgetc($f);

/**
* Trim trailing newline chars of the file
*/
while ($char === "\n" || $char === "\r") {
    fseek($f, $cursor--, SEEK_END);
    $char = fgetc($f);
}

/**
* Read until the start of file or first newline char
*/
while ($char !== false && $char !== "\n" && $char !== "\r") {
    /**
     * Prepend the new char
     */
    $line = $char . $line;
    fseek($f, $cursor--, SEEK_END);
    $char = fgetc($f);
}

return $line;
}

echo read_last_line('log.txt');

echo read_last_line('log.txt');

you will get that last line

你会得到最后一行

回答by slikts

You're looking for the fseekfunction. There are working examples of how to read the last line of a file in the comments section there.

您正在寻找fseek函数。在那里的评论部分有一些关于如何读取文件最后一行的工作示例。

回答by Lawrence Barsanti

If you know the upper bound of line length you could do something like this.

如果你知道行长的上限,你可以做这样的事情。

$maxLength = 1024;
$fp = fopen('somefile.txt', 'r');
fseek($fp, -$maxLength , SEEK_END); 
$fewLines = explode("\n", fgets($fp, $maxLength));
$lastLine = $fewLines[count($fewLines) - 1];

In response to the edit: fopen just acquires a handle to the file (i.e. make sure it exists, process has permission, lets os know a process is using the file, etc...). In this example only 1024 characters from the file will be read into memory.

响应编辑: fopen 只是获取文件的句柄(即确保它存在,进程具有权限,让操作系统知道进程正在使用该文件等......)。在这个例子中,文件中只有 1024 个字符会被读入内存。

回答by Daniel A. White

function readlastline() 
{ 
       $fp = @fopen("/dosmnt/LOGFILE.DAT", "r"); 
       $pos = -1; 
       $t = " "; 
       while ($t != "\n") { 
             fseek($fp, $pos, SEEK_END); 
             $t = fgetc($fp); 
             $pos = $pos - 1; 
       } 
       $t = fgets($fp); 
       fclose($fp); 
       return $t; 
} 

Source: http://forums.devshed.com/php-development-5/php-quick-way-to-read-last-line-156010.html

来源:http: //forums.devshed.com/php-development-5/php-quick-way-to-read-last-line-156010.html

回答by James Goodwin

Your problem looks similar to this one

您的问题与类似

The best approach to avoid loading the whole file into memory seems to be:

避免将整个文件加载到内存中的最佳方法似乎是:

$file = escapeshellarg($file); // for the security concious (should be everyone!)
$line = `tail -n 1 $file`;

回答by Wolph

Would it be possible to optimize this from the other side? If so, just let the logging application always log the line to a file while truncating it (i.e. > instead of >>)

是否有可能从另一边优化这一点?如果是这样,只需让日志记录应用程序在截断它时始终将行记录到文件中(即 > 而不是 >>)

Some optimization might be achieved by "guessing" though, just open the file and with the average log line width you could guess where the last line would be. Jump to that position with fseek and find the last line.

不过,可以通过“猜测”来实现一些优化,只需打开文件并使用平均日志行宽,您就可以猜测最后一行的位置。使用 fseek 跳转到该位置并找到最后一行。

回答by Syntax Error

Untested code from the comments of http://php.net/manual/en/function.fseek.php

来自http://php.net/manual/en/function.fseek.php评论的未经测试的代码

jim at lfchosting dot com 05-Nov-2003 02:03
Here is a function that returns the last line of a file.  This should be quicker than reading the whole file till you get to the last line.  If you want to speed it up a bit, you can set the $pos = some number that is just greater than the line length.  The files I was dealing with were various lengths, so this worked for me. 

<?php 
function readlastline($file) 
{ 
        $fp = @fopen($file, "r"); 
        $pos = -1; 
        $t = " "; 
        while ($t != "\n") { 
              fseek($fp, $pos, SEEK_END); 
              $t = fgetc($fp); 
              $pos = $pos - 1; 
        } 
        $t = fgets($fp); 
        fclose($fp); 
        return $t; 
} 
?>

回答by caiofior

This is my solution with only one loop

这是我只有一个循环的解决方案

        $line = '';
        $f = fopen($file_path, 'r');
        $cursor = 0 ;
        do  {
            fseek($f, $cursor--, SEEK_END);
            $char = fgetc($f);
            $line = $char.$line;
        } while (
                $cursor > -1 || (
                 ord($char) !== 10 &&
                 ord($char) !== 13
                )
        );