从头读取大文件

kri*_*tya 12 php file-io

我可以从我的最终读取PHP文件,例如,如果我想阅读最后10-20行吗?

而且,正如我读到的,如果文件的大小超过10mbs,我开始得到错误.

我该如何防止此错误?

为了阅读普通文件,我们使用以下代码:

if ($handle) {
    while (($buffer = fgets($handle, 4096)) !== false) {
    $i1++;
    $content[$i1]=$buffer;
    }
    if (!feof($handle)) {
        echo "Error: unexpected fgets() fail\n";
    }
    fclose($handle);
}
Run Code Online (Sandbox Code Playgroud)

我的文件可能超过10mbs,但我只需阅读最后几行.我该怎么做?

谢谢

Gre*_*sha 17

您可以使用fopen和fseek从末尾向后导航文件.例如

$fp = @fopen($file, "r");
$pos = -2;
while (fgetc($fp) != "\n") {
    fseek($fp, $pos, SEEK_END);
    $pos = $pos - 1;
}
$lastline = fgets($fp);
Run Code Online (Sandbox Code Playgroud)

  • 对此进行轻微更新.似乎fseek在内部使用ints,这会阻止您在32位设置上设置位置超过2147483647.这使我无法在大约4.8gb的日志文件上使用它. (5认同)
  • +1因为它允许打开远程文件 (2认同)

pha*_*t0m 6

这取决于你如何解释"可以".

如果您想知道是否可以直接执行此操作(使用PHP函数)而不读取前面所有的行,那么答案是:,您不能.

行结尾是对数据的解释,如果您实际读取数据,则只能知道它们的位置.

如果它是一个非常大的文件,我不会这样做.如果你从最后开始扫描文件会更好,并逐渐从末尾读取块到文件.

更新

这是一种只读PHP的方法来读取文件的最后n行而不读取所有文件:

function last_lines($path, $line_count, $block_size = 512){
    $lines = array();

    // we will always have a fragment of a non-complete line
    // keep this in here till we have our next entire line.
    $leftover = "";

    $fh = fopen($path, 'r');
    // go to the end of the file
    fseek($fh, 0, SEEK_END);
    do{
        // need to know whether we can actually go back
        // $block_size bytes
        $can_read = $block_size;
        if(ftell($fh) < $block_size){
            $can_read = ftell($fh);
        }

        // go back as many bytes as we can
        // read them to $data and then move the file pointer
        // back to where we were.
        fseek($fh, -$can_read, SEEK_CUR);
        $data = fread($fh, $can_read);
        $data .= $leftover;
        fseek($fh, -$can_read, SEEK_CUR);

        // split lines by \n. Then reverse them,
        // now the last line is most likely not a complete
        // line which is why we do not directly add it, but
        // append it to the data read the next time.
        $split_data = array_reverse(explode("\n", $data));
        $new_lines = array_slice($split_data, 0, -1);
        $lines = array_merge($lines, $new_lines);
        $leftover = $split_data[count($split_data) - 1];
    }
    while(count($lines) < $line_count && ftell($fh) != 0);
    if(ftell($fh) == 0){
        $lines[] = $leftover;
    }
    fclose($fh);
    // Usually, we will read too many lines, correct that here.
    return array_slice($lines, 0, $line_count);
}
Run Code Online (Sandbox Code Playgroud)


Suk*_*ngh 6

以下片段对我有用。

$file = popen("tac $filename",'r');

while ($line = fgets($file)) {

   echo $line;
Run Code Online (Sandbox Code Playgroud)

}

参考:http : //laughingmeme.org/2008/02/28/reading-a-file-backwards-in-php/


Era*_*rin 5

它不是纯PHP,但常见的解决方案是使用tac命令,它是revert cat并反向加载文件.使用exec()或passthru()在服务器上运行它,然后读取结果.用法示例:

<?php
$myfile = 'myfile.txt';
$command = "tac $myfile > /tmp/myfilereversed.txt";
exec($command);
$currentRow = 0;
$numRows = 20;  // stops after this number of rows
$handle = fopen("/tmp/myfilereversed.txt", "r");
while (!feof($handle) && $currentRow <= $numRows) {
   $currentRow++;
   $buffer = fgets($handle, 4096);
   echo $buffer."<br>";
}
fclose($handle);
?>
Run Code Online (Sandbox Code Playgroud)