如何在PHP中只读取文本文件的最后5行?

如何在PHP中只读取文本文件的最后5行?,php,fopen,Php,Fopen,我有一个名为file.txt的文件,它通过添加行来更新 我通过以下代码阅读: $fp = fopen("file.txt", "r"); $data = ""; while(!feof($fp)) { $data .= fgets($fp, 4096); } echo $data; 出现了大量的线条。 我只想回显文件的最后5行 我该怎么做 file.txt如下所示: 11111111111111 22222222222 33333333333333 44444444444 5555555

我有一个名为
file.txt
的文件,它通过添加行来更新

我通过以下代码阅读:

$fp = fopen("file.txt", "r");
$data = "";
while(!feof($fp))
{
$data .= fgets($fp, 4096);
}
echo $data;
出现了大量的线条。 我只想回显文件的最后5行

我该怎么做


file.txt
如下所示:

11111111111111
22222222222

33333333333333
44444444444

55555555555555
66666666666

如果行之间用CR或LF分隔,请尝试使用$data变量:

$lines = explode("\n", $data);

$lines应该是一个数组,您可以使用sizeof()计算出记录的数量,只需得到最后5条。

未测试的代码,但应该可以:

$file = file("filename.txt");
for ($i = max(0, count($file)-6); $i < count($file); $i++) {
  echo $file[$i] . "\n";
}
$file=file(“filename.txt”);
对于($i=max(0,count($file)-6);$i
调用
max
将处理少于6行的文件。

函数ReadFromEndByLine($filename,$lines)
function ReadFromEndByLine($filename,$lines)
{

        /* freely customisable number of lines read per time*/
        $bufferlength = 5000;

        $handle = @fopen($filename, "r");
        if (!$handle) {
                echo "Error: can't find or open $filename<br/>\n";
                return -1;
        }

        /*get the file size with a trick*/
        fseek($handle, 0, SEEK_END);
        $filesize = ftell($handle);

        /*don't want to get past the start-of-file*/
        $position= - min($bufferlength,$filesize);

        while ($lines > 0) {

                if ($err=fseek($handle,$position,SEEK_END)) {  /* should not happen but it's better if we check it*/
                        echo "Error $err: something went wrong<br/>\n";
                        fclose($handle);
                        return $lines;
                }

                /* big read*/
                $buffer = fread($handle,$bufferlength);

                /* small split*/
                $tmp = explode("\n",$buffer);

                /*previous read could have stored a partial line in $aliq*/
                if ($aliq != "") {

                                /*concatenate current last line with the piece left from the previous read*/
                                $tmp[count($tmp)-1].=$aliq;
                }

                /*drop first line because it may not be complete*/
                $aliq = array_shift($tmp);

                $read = count($tmp);
                if ( $read >= $lines ) {   /*have read too much!*/

                        $tmp2 = array_slice($tmp,$read-$n);
                        /* merge it with the array which will be returned by the function*/
                        $lines = array_merge($tmp2,$lines);

                        /* break the cycle*/
                        $lines = 0;
                } elseif (-$position >= $filesize) {  /* haven't read enough but arrived at the start of file*/

                        //get back $aliq which contains the very first line of the file
                        $lines = array_merge($aliq,$tmp,$lines);

                        //force it to stop reading
                        $lines = 0;

                } else {              /*continue reading...*/

                        //add the freshly grabbed lines on top of the others
                        $lines = array_merge($tmp,$lines);

                        $lines -= $read;

                        //next time we want to read another block
                        $position -= $bufferlength;

                        //don't want to get past the start of file
                        $position = max($position, -$filesize);
                }
        }
        fclose($handle);

        return $lines;
}
{ /*可自由定制每次读取的行数*/ $bufferlength=5000; $handle=@fopen($filename,“r”); 如果(!$handle){ echo“错误:无法找到或打开$filename
\n”; 返回-1; } /*使用技巧获取文件大小*/ fseek($handle,0,SEEK\u END); $filesize=ftell($handle); /*不想超过文件的开头*/ $position=-min($bufferlength,$filesize); 而($line>0){ 如果($err=fseek($handle,$position,SEEK_END)){/*不应该发生,但最好检查一下*/ echo“Error$err:出现问题
\n”; fclose($handle); 返回$line; } /*博览群书*/ $buffer=fread($handle,$bufferlength); /*小裂口*/ $tmp=explode(“\n”,$buffer); /*以前的读取可能在$aliq中存储了部分行*/ 如果($aliq!=“”){ /*将当前最后一行与上一次读取的剩余部分连接起来*/ $tmp[count($tmp)-1]。=$aliq; } /*删除第一行,因为它可能不完整*/ $aliq=阵列移位($tmp); $read=计数($tmp); 如果($read>=$line){/*读得太多了*/ $tmp2=阵列片($tmp,$read-$n); /*将其与函数返回的数组合并*/ $lines=数组合并($tmp2,$lines); /*打破循环*/ $lines=0; }elseif(-$position>=$filesize){/*尚未读取足够的内容,但已到达文件的开头*/ //获取$aliq,它包含文件的第一行 $lines=array\u merge($aliq、$tmp、$lines); //强迫它停止阅读 $lines=0; }否则{/*继续阅读*/ //将新抓取的线条添加到其他线条之上 $lines=数组合并($tmp,$lines); $lines-=$read; //下一次我们想读另一块 $position-=$bufferlength; //不想超过文件的开头 $position=max($position,-$filesize); } } fclose($handle); 返回$line; }
对于较大的文件,这将是快速的,但是对于一个简单的任务,有很多代码,如果有较大的文件,使用这个


ReadFromEndByLine('myFile.txt',6)

对于大文件,使用file()将所有行读入数组有点浪费。以下是如何读取文件并维护最后5行的缓冲区:

$lines=array();
$fp = fopen("file.txt", "r");
while(!feof($fp))
{
   $line = fgets($fp, 4096);
   array_push($lines, $line);
   if (count($lines)>5)
       array_shift($lines);
}
fclose($fp);
您可以使用一些关于可能的线长度的启发式方法对此进行进一步优化,方法是寻找一个位置,例如,距离末端大约10行,如果不产生5行,则返回更远的位置。下面是一个简单的实现,它演示了:

//how many lines?
$linecount=5;

//what's a typical line length?
$length=40;

//which file?
$file="test.txt";

//we double the offset factor on each iteration
//if our first guess at the file offset doesn't
//yield $linecount lines
$offset_factor=1;


$bytes=filesize($file);

$fp = fopen($file, "r") or die("Can't open $file");


$complete=false;
while (!$complete)
{
    //seek to a position close to end of file
    $offset = $linecount * $length * $offset_factor;
    fseek($fp, -$offset, SEEK_END);


    //we might seek mid-line, so read partial line
    //if our offset means we're reading the whole file, 
    //we don't skip...
    if ($offset<$bytes)
        fgets($fp);

    //read all following lines, store last x
    $lines=array();
    while(!feof($fp))
    {
        $line = fgets($fp);
        array_push($lines, $line);
        if (count($lines)>$linecount)
        {
            array_shift($lines);
            $complete=true;
        }
    }

    //if we read the whole file, we're done, even if we
    //don't have enough lines
    if ($offset>=$bytes)
        $complete=true;
    else
        $offset_factor*=2; //otherwise let's seek even further back

}
fclose($fp);

var_dump($lines);
//有多少行?
$linecount=5;
//典型的线路长度是多少?
$length=40;
//哪个文件?
$file=“test.txt”;
//我们在每次迭代中将偏移因子加倍
//如果我们对文件偏移量的第一次猜测不正确
//产生$linecount行
$offset_系数=1;
$bytes=文件大小($file);
$fp=fopen($file,“r”)或die(“无法打开$file”);
$complete=false;
while(!$complete)
{
//搜索到靠近文件末尾的位置
$offset=$linecount*$length*$offset\u因子;
fseek($fp,-$offset,SEEK_END);
//我们可能会寻找中间线,所以请阅读部分线
//如果偏移量意味着我们正在读取整个文件,
//我们不会跳过。。。
如果($offset$linecount)
{
数组移位($行);
$complete=true;
}
}
//如果我们读了整个文件,就算我们
//没有足够的线路
如果($offset>=$bytes)
$complete=true;
其他的
$offset_系数*=2//否则,让我们再往回看
}
fclose($fp);
var_转储(行);
PHP函数将整个文件读取到一个数组中。 此解决方案需要最少的键入次数:

$data = array_slice(file('file.txt'), -5);

foreach ($data as $line) {
    echo $line;
}

如果您使用的是linux系统,则可以执行以下操作:

$lines = `tail -5 /path/to/file.txt`;
否则,您必须数数行数并取最后5行,类似于:

$all_lines = file('file.txt');
$last_5 = array_slice($all_lines , -5);

这是一个常见的面试问题。这是我去年被问到这个问题时写的。请记住,在堆栈溢出上获得的代码是使用许可的


我已经测试过这个了。它对我有用

function getlast($filename,$linenum_to_read,$linelength){

   // this function takes 3 arguments;


   if (!$linelength){ $linelength = 600;}
$f = fopen($filename, 'r');
$linenum = filesize($filename)/$linelength;

    for ($i=1; $i<=($linenum-$linenum_to_read);$i++) {
    $data = fread($f,$linelength);
    }
echo "<pre>";       
    for ($j=1; $j<=$linenum_to_read+1;$j++) {
    echo fread($f,$linelength);
    }

echo "</pre><hr />The filesize is:".filesize("$filename");
}

getlast("file.txt",6,230);


?>
函数getlast($filename,$linenum\u to\u read,$linelength){ //这个函数有3个参数; 如果(!$linelength){$linelength=600;} $f=fopen($filename,'r'); $linenum=filesize($filename)/$linelength; 对于($i=1;$i)
这不使用
文件()
,因此对于大型文件来说效率更高

// Will seek backwards $n lines from the current position
function seekLineBackFast($fh, $n = 1){
    $pos = ftell($fh);
    if ($pos == 0)
        return false;

    $posAtStart = $pos;

    $readSize = 2048*2;
    $pos = ftell($fh);
    if(!$pos){
            fseek($fh, 0, SEEK_SET);
            return false;
    }

    // we want to seek 1 line before the line we want.
    // so that we can start at the very beginning of the line
    while ($n >= 0) {
        if($pos == 0)
                    break;
            $pos -= $readSize;
            if($pos <= 0){
                    $pos = 0;
            }

            // fseek returns 0 on success and -1 on error
            if(fseek($fh, $pos, SEEK_SET)==-1){
                    fseek($fh, 0, SEEK_SET);
                    break;
            }
            $data = fread($fh, $readSize);
            $count = substr_count($data, "\n");
            $n -= $count;

            if($n < 0)
                    break;
    }
    fseek($fh, $pos, SEEK_SET);
    // we may have seeked too far back
    // so we read one line at a time forward
    while($n < 0){
            fgets($fh);
            $n++;
    }
    // just in case?
    $pos = ftell($fh);
    if(!$pos)
        fseek($fh, 0, SEEK_SET);

    // check that we have indeed gone back
    if ($pos >= $posAtStart)
        return false;

    return $pos;
}

此功能将真正适用于l
<?php
function read_backward_line($filename, $lines, $revers = false)
{
    $offset = -1;
    $c = '';
    $read = '';
    $i = 0;
    $fp = @fopen($filename, "r");
    while( $lines && fseek($fp, $offset, SEEK_END) >= 0 ) {
        $c = fgetc($fp);
        if($c == "\n" || $c == "\r"){
            $lines--;
            if( $revers ){
                $read[$i] = strrev($read[$i]);
                $i++;
            }
        }
        if( $revers ) $read[$i] .= $c;
        else $read .= $c;
        $offset--;
    }
    fclose ($fp);
    if( $revers ){
        if($read[$i] == "\n" || $read[$i] == "\r")
            array_pop($read);
        else $read[$i] = strrev($read[$i]);
        return implode('',$read);
    }
    return strrev(rtrim($read,"\n\r"));
}
//if $revers=false function return->
//line 1000: i am line of 1000
//line 1001: and i am line of 1001
//line 1002: and i am last line
//but if $revers=true function return->
//line 1002: and i am last line
//line 1001: and i am line of 1001
//line 1000: i am line of 1000
?>
// Will seek backwards $n lines from the current position
function seekLineBackFast($fh, $n = 1){
    $pos = ftell($fh);
    if ($pos == 0)
        return false;

    $posAtStart = $pos;

    $readSize = 2048*2;
    $pos = ftell($fh);
    if(!$pos){
            fseek($fh, 0, SEEK_SET);
            return false;
    }

    // we want to seek 1 line before the line we want.
    // so that we can start at the very beginning of the line
    while ($n >= 0) {
        if($pos == 0)
                    break;
            $pos -= $readSize;
            if($pos <= 0){
                    $pos = 0;
            }

            // fseek returns 0 on success and -1 on error
            if(fseek($fh, $pos, SEEK_SET)==-1){
                    fseek($fh, 0, SEEK_SET);
                    break;
            }
            $data = fread($fh, $readSize);
            $count = substr_count($data, "\n");
            $n -= $count;

            if($n < 0)
                    break;
    }
    fseek($fh, $pos, SEEK_SET);
    // we may have seeked too far back
    // so we read one line at a time forward
    while($n < 0){
            fgets($fh);
            $n++;
    }
    // just in case?
    $pos = ftell($fh);
    if(!$pos)
        fseek($fh, 0, SEEK_SET);

    // check that we have indeed gone back
    if ($pos >= $posAtStart)
        return false;

    return $pos;
}
//read last 5 lines
$lines = \jasir\FileHelpers\FileHelpers::readLastLines($pathToFile, 5);
$data = array_slice(file('logs.txt'),10);

    foreach ($data as $line) 

    {

        echo $line."<br/>";
    }
$lines=array();
$fp = fopen("userlog.txt", "r");
while(!feof($fp))
{
 $line = fgets($fp, 4096);
 array_push($lines, $line);
 if (count($lines)>25)
   array_shift($lines);
}
fclose($fp);

while ($a <= 10) {
$a++;
echo "<br>".$lines[$a];
}
$dosya = "../dosya.txt";
$array = explode("\n", file_get_contents($dosya));
$reversed = array_reverse($array);
for($x = 0; $x < 6; $x++) 
{
    echo $reversed[$x];
}
$file = new SplFileObject('large_file.txt', 'r');

$file->seek(PHP_INT_MAX);

$last_line = $file->key();

$lines = new LimitIterator($file, $last_line - 5, $last_line);

print_r(iterator_to_array($lines));
exec('tail -3 /logs/reports/2017/02-15/173606-arachni-2415.log', $output);
echo $output;

// 2017-02-15 18:03:25 [*] Path Traversal: Analyzing response ...
// 2017-02-15 18:03:27 [*] Path Traversal: Analyzing response ...
// 2017-02-15 18:03:27 [*] Path Traversal: Analyzing response ...
/**
 *
 * Reads N lines from a file
 *
 * @param type $file       path
 * @param type $maxLines   Count of lines to read
 * @param type $reverse    set to true if result should be reversed.
 * @return string
 */
public function readLinesFromFile($file, $maxLines, $reverse=false)
{
    $lines = file($file);

    if ($reverse) {
        $lines = array_reverse($lines);
    }

    $tmpArr = array();

    if ($maxLines > count($lines))
        exit("\$maxLines ist größer als die Anzahl der Zeilen in der Datei.");

    for ($i=0; $i < $maxLines; $i++) {
        array_push($tmpArr, $lines[$i]);
    }

    if ($reverse) {
        $tmpArr = array_reverse($tmpArr);
    }

    $out = "";
    for ($i=0; $i < $maxLines; $i++) {
        $out .= $tmpArr[$i] . "</br>";
    }

    return $out;
}
function readLastLines($filename, $num, $reverse = false)
{
    $file = new \SplFileObject($filename, 'r');
    $file->seek(PHP_INT_MAX);
    $last_line = $file->key();
    $lines = new \LimitIterator($file, $last_line - $num, $last_line);
    $arr = iterator_to_array($lines);
    if($reverse) $arr = array_reverse($arr);
    return implode('',$arr);
}

// use it by
$lines = readLastLines("file.txt", 5) // return string with 5 last lines